xccjk / x-blog

学习笔记
17 stars 2 forks source link

浅谈前端模块化 #52

Closed xccjk closed 2 years ago

xccjk commented 3 years ago

前端模块化

CommonJS

// a.js
function test1() {
  console.log('test 1')
}
function test2() {
console.log('test 2')
}

// 通过module.exports导出模块
module.exports = {
  test1,
  test2
}

// 或者
module.exports = test1

// 通过exports导出模块
exports.fn = test1

// b.js
// 通过require来加载模块

// 核心模块加载
const http = require('http')

// 加载module.exports导出的模块
const { test1, test2 } = require('./a')
test1() // test 1

// 加载exports导出的模块
const test = require('./a.js')
test.fn() // test 1

AMD

// 模块定义
/*
  id: 可选,定义模块表示
  dependencies: 当前模块依赖模块列表
  factory: 工厂方法,表示模块初始化需要执行的函数或者对象
*/
define(id?, dependencies, factory)

// 模块加载
/*
  dependencies: 需要加载的模块文件
  fn: 模块加载完成的回调
*/
require([dependencies], fn)
// 定义
// a.js
define(['jquery'], function($) {
  function test() {
    console.log($('#app'))
  }
  return {
    test
  }
})

// 加载
// b.js
require(['a.js'], function(t) {
  t.test()
})

CMD

// AMD实现
define(['a', 'b', 'c'], function(a, b, c) {
  // 在执行到回调函数中时,实际模块a,b,c已经都加载完成
  a.fn1()
  b.fn1()
  c.fn1()
})

// CMD实现
define(function(require, exports, module) {
  const a = require('./a')
  a.fn1()
  if (false) {
    const b = require('./b')
    b.fn1()
  }
})

ES Module

// 定义模块
// a.js
function test1() {
  console.log('test 1')
}

export {
  test1
}

// b.js
function test2() {
  console.log('test 2')
}

function test3() {
  console.log('test 3')
}

export default {
  test2,
  test3
}

// 引入模块
// c.js
import { test1 } from './a'
import math from './b'
test1()
math.test2()
// a.js
function func() {
  console.log('func a')
}

function bar() {
  console.log('bar')
}

// b.js
function func() {
  console.log('func b')
}

import React from 'react'
// 在import时使用as来区分别名
import { func as fu, bar } from './a'
import { func } from './a'

export class MyClass extends React.Component {
    ...
}
// 通过export default指定默认输出
// a.js
export default function() {
  console.log('test 1')
}
// b.js
export function test2() {
console.log('test 2')
}
// c.js
import Test1 from './a'
import { Test2 } from '/b'
// 浏览器中直接使用,通过type='module'来识别es6模块
// a.js
const name = 'xcc'
export default xcc

// index.html
<script type="module">
  import name from './a.js'
  console.log(name) // xcc
</script>

注意的点

// CommonJS加载
// 基本数据类型导出后不可修改,为复杂数据类型时,实际是一个浅拷贝,可以进行修改
// a.js
let name = 'xcc'
let obj = { name: 'xcc', age: 20 }

function setName() {
  name = 'xcc1'
}

function setName1() {
  obj.name = 'xcc2'
}

module.exports = {
  name,
  info: obj,
  setName,
  setName1
}

// b.js
let { name, info, setName, setName1 } = require('./a.js')

setName()
setName1()

console.log(name, info) // xcc { name: 'xcc2', age: 20 }
// ES Module
// 导出后还可以随便修改
// c.js
let name = 'xcc'
let obj = { name: 'xcc', age: 20 }

function setName() {
  name = 'xcc1'
}

function setName1() {
  obj.name = 'xcc2'
}

export {
  name,
  obj,
  setName,
  setName1
}

// index.html
<script type="module">
  import { name, obj, setName, setName1 } from './c.js'
  setName()
  setName1()
  console.log(name, obj)  // xcc1 {name: "xcc2", age: 20}
</script>

参考资料