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>
    

    参考资料

  • 相关阅读:
    ExecuteScalar requires the command to have a transaction when the connection assigned to the command is in a pending
    如何从vss中分离程序
    String or binary data would be truncated
    the pop3 service failed to retrieve authentication type and cannot continue
    The POP3 service failed to start because
    IIS Error he system cannot find the file specified _找不到页面
    pku2575Jolly Jumpers
    pku2940Wine Trading in Gergovia
    pku3219二项式系数
    pku1029false coin
  • 原文地址:https://www.cnblogs.com/sk-3/p/14678784.html
Copyright © 2011-2022 走看看