zoukankan      html  css  js  c++  java
  • AMD、CMD、CommonJS 和 ES6 模块化规范

    演变历史

        早期(全局函数模式)
        Global 被污染,很容易命名冲突

    function foo(){}
    function bar(){}

        1
        2

        中期(命名空间模式)
        本质是对象,可以被操作修改,不安全

    var DO = {
        foo: function () { },
        bar: function () { }
    }
    DO.foo()

        1
        2
        3
        4
        5

        后期(IIFE模式)
        立即执行函数

    (function ($) {
        function foo() {
            console.log($); // window 对象
        }
        function bar() { }
        $.module = { foo: foo, bar: bar }
    })(window)
    module.foo()

        1
        2
        3
        4
        5
        6
        7
        8

    问题:上面的几种方式尽管可以模块化,但是请求过多、依赖模糊、难以维护,还是达不到想要的目的,所以产生了四种模块化规范(AMD、CMD、CommonJS、ES6)

    问题举例:

    // js/module.js
    (function ($) {
        let fun = 'i am module'
        function out() {
            return fun
        }
        $.module = { out }
    })(window)

    // js/app.js
    (function ($) {
        let fun = 'i am app'
        function out() {
            console.log(fun, '————', module.out())
        }
        $.app = { out }
    })(window, module)

    // index.html
    <script src="./js//module.js"></script>
    <script src="./js/app.js"></script>
    <script>
        app.out() // i am app ———— i am module
    </script>

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24

    模块化目的

        降低复杂度
        提升解耦性
        避免命名冲突
        部署方便,复用性强,按需加载
        可维护性好

    AMD

        RequireJS 在推广过程中对模块定义的规范化产出
        依赖前置,异步模块定义,在使用前需要先定义
        专门用于浏览器端,模块的加载是异步的

    基本语法:官方文档

        暴露模块

    // 定义有依赖的模块
    // 数组内放置依赖的模块,回调内形参对应前面依赖的模块
    define(['module1','module2'], function(m1, m2) {
        'use strict';
        // return 模块
    });

    // 定义没有依赖的模块
    define(function() {
        'use strict';
        // return 模块
    });

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12

        引入模块

    require(['module1','module2'], function(m1, m2) {
        // 使用 m1、m2
    })

        1
        2
        3

    实例:

    // js/libs/module1.js
    // 定义有依赖的模块
    define(['module2'], function (module2) {
        let msg = 'module1'
        function showMsg() {
            console.log(msg, '————', module2.out());
        }
        // 暴露模块
        return { showMsg }
    });

    // js/libs/module2.js
    // 定义没有依赖的模块
    define(function () {
        let msg = 'module2'
        function out() {
            return msg
        }
        // 暴露模块
        return { out }
    });

    // js/main.js
    (function () {
        requirejs.config({ // 配置模块
            //By default load any module IDs from js/lib
            baseUrl: 'js/', // 基本路径,出发点在根路径下

            //except, if the module ID starts with "app",
            //load it from the js/app directory. paths
            //config is relative to the baseUrl, and
            //never includes a ".js" extension since
            //the paths config could be for a directory.
            paths: { // 配置路径,注意尾部不要带 .js
                // app: '../app'
                module1: './libs/module1',
                module2: './libs/module2',
            }
        })

        requirejs(['module1'], function (module1) {
            module1.showMsg()
        })
    })();

    // app.html
    <script data-main='js/main' src='js/libs/require.js'></script>
    // data-main 用于指向主文件

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        33
        34
        35
        36
        37
        38
        39
        40
        41
        42
        43
        44
        45
        46
        47
        48

    CMD

        SeaJS 在推广过程中对模块定义的规范化产出
        依赖就近,同步模块定义,即用即返回
        专门用于浏览器端,模块的加载是异步的

    基本语法:官方文档

        暴露模块

    // 定义有依赖的模块
    define(function (require, exports, module) {
        // 引入依赖模块(同步)
        var module2 = require('./module2')
        // 引入依赖模块(异步)
        require.async('./module3', function (m3) {
            // m3 模块引入成功后在回调内直接使用
        })
        // 暴露模块
        exports.xxx = value
    })

    // 定义没有依赖的模块
    define(function (require, exports, module) {
        // 暴露模块
        exports.xxx = value
        module.exports = value
    })

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18

        引入模块

    define(function (require) {
        var m1 = require('./module1')
        var m4 = require('./module4')
        m1.show()
        m4.show()
    })

        1
        2
        3
        4
        5
        6

    实例:

    // js/libs/module1.js
    // 定义有依赖的模块
    define(function (require, exports, module) {
        // 异步引入
        require.async('./module2', function (m2) {
            console.log(m2.out());
        })
        
        // 同步引入
        let module2 = require('./module2')
        let msg = 'module1'
        function showMsg() {
            console.log(msg, '————', module2.out());
        }

        // 暴露模块
        module.exports = showMsg
    });

    // js/libs/module2.js
    // 定义没有依赖的模块
    define(function (require, exports, module) {
        let msg = 'module2'
        function out() {
            return msg
        }
        module.exports = { out }
    });

    // js/main.js
    define(function (require) {
        let module1 = require('./libs/module1')
        module1() // module2 / module1 ———— module2
    })

    // app.html
    <script src='js/libs/sea.js'></script>
    <script>
        seajs.use('./js/main.js')
    </script>

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        33
        34
        35
        36
        37
        38
        39
        40

    CommonJS

        每个文件都可当做一个模块
        在服务器端:模块的加载是运行时同步加载的
        在浏览器端:模块需要提前编译(Browserify)打包处理(在浏览器端推荐 ES6 模块化,因为同步等待时间长,性能差)

    基本语法:更多

    // 模块暴露
    // 本质暴露的是 exports 对象(初始 exports 为 {})
    module.exports = value
    exports.xxx = value
    console.log(exports === module.exports) // true

    // 引入模块
    require(xxx) // 第三方模块直接引入,自定义模块按路径引入

        1
        2
        3
        4
        5
        6
        7
        8

    ES6

    基本语法:更多

    // 暴露模块
    export default value
    export let a = { name: 'foo' }
    export let b = { name: 'bar' }

    // 引入模块
    import value from '../path1'
    import { a, b } from './path2'

        1
        2
        3
        4
        5
        6
        7
        8

    AMD 与 CMD 差异

        AMD 是 RequireJS 在推广过程中对模块定义提出的概念。
        CMD 是 SeaJS 在推广过程中对模块定义提出的概念。

    RequireJS 和 Sea.js 都是模块加载器,倡导模块化开发理念,核心价值是让 JavaScript 的模块化开发变得简单自然。
    不同之处,两者的主要区别如下:

        定位有差异。RequireJS 想成为浏览器端的模块加载器,同时也想成为 Rhino / Node 等环境的模块加载器。Sea.js 则专注于 Web 浏览器端,同时通过 Node 扩展的方式可以很方便跑在 Node 环境中。
        遵循的规范不同。RequireJS 遵循 AMD(异步模块定义)规范,Sea.js 遵循 CMD (通用模块定义)规范。规范的不同,导致了两者 API 不同。Sea.js 更贴近 CommonJS Modules/1.1 和 Node Modules 规范。
        CMD 推崇依赖就近,AMD 推崇依赖前置。
        推广理念有差异。RequireJS 在尝试让第三方类库修改自身来支持 RequireJS,目前只有少数社区采纳。Sea.js 不强推,采用自主封装的方式来“海纳百川”,目前已有较成熟的封装策略。
        对开发调试的支持有差异。Sea.js 非常关注代码的开发调试,有 nocache、debug 等用于调试的插件。RequireJS 无这方面的明显支持。
        插件机制不同。RequireJS 采取的是在源码中预留接口的形式,插件类型比较单一。Sea.js 采取的是通用事件机制,插件类型更丰富。
    ————————————————
    版权声明:本文为CSDN博主「肖ZE」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/lucky541788/java/article/details/88967378

  • 相关阅读:
    mybatis的注意事项一
    java代码操作word模板生成PDF文件
    使用mybatis框架实现带条件查询多条件(传入实体类)
    MyBatis框架ResultMap节点
    优化mybatis框架中的查询用户记录数的案例
    Mybatis框架联表查询显示问题解决
    使用mybatis框架实现带条件查询单条件
    [DB] 如何彻底卸载删除MySQL 【MYSQL】
    [DB] MySQL窗口输入密码后消失问题 【MYSQL】
    [acm] 曾经 刷题记录 [只有正确的坚持才是胜利]
  • 原文地址:https://www.cnblogs.com/fs0196/p/13048371.html
Copyright © 2011-2022 走看看