zoukankan      html  css  js  c++  java
  • 前端模块化:CommonJS,AMD,CMD,ES6

    前端模块化

    CommonJS

    • nodejs使用的规范
    • 文件即模块,通过指定的方式进行导出
    • /表示通过绝对路径来加载模块,./表示通过相对路径来加载模块
    • 模块加载会有缓存存在,存放在require.cache中,并且缓存是根据绝对路径来识别的
    • CommonJS是同步加载的,加载完成之后再进行下面的操作
    • 运行时加载,CommonJS就是对象,在输入时先加载整个模块,生成一个对象,然后在从这个对象上面读取方法
    • 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

    • 采用异步方式加载模块,模块加载不影响后面的语句运行
    • 存在依赖关系的模块,会在依赖的模块的回调函数中执行
    • requirejs实现了AMD规范的模块化
    • 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

    • 通用模块定义
    • 异步加载模块
    • 依赖就近,延迟执行
    • seajs实现了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

    • 通过es6的语言标准层面上实现模块功能,旨在成为浏览器与服务端通用的模块化解决方案
    • 编译时加载,ES6模块不是对象,而是通过export命令显式指定输出代码。import是采用静态命令的形式,可以加载指定的某个输出值,而不是加载整个模块
    • 通过export来导出接口,通过import引入接口
    • js引擎对脚本静态分析时,遇到模块加载命令import,会输出一个只读的引用。等到脚本真正执行时,再取实际导出的值
    // 定义模块
    // 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>
    

    参考资料

  • 相关阅读:
    Makefile目标汇总和变量的高级用法
    make命令详解
    再议HTML Clipboard Format
    编写一个Open Live Writer的VSCode代码插件
    win7安装ps cc 2019切片闪退
    redis cluster 数据迁移
    linux服务器两块网卡路由优先级冲突 Metric值(转)
    电梯怎么测,附常见的测试用例
    vue中watch属性深度监听,监听数组或多维数组下层
    前端JS base64与图片互转
  • 原文地址:https://www.cnblogs.com/sk-3/p/14678784.html
Copyright © 2011-2022 走看看