zoukankan      html  css  js  c++  java
  • js模块化AMD、CMD、ES6

    • AMD
    • CMD
    • ES6模块化
    • 各个模块化规范对比理解

     一、AMD

    在上一篇js模块化入门与commonjs解析与应用中详细的解析了关于commonjs模块化规范,commonjs采用的用同步加载方式,这导致它并不是浏览器理想的模块化规范。因为浏览器需要到服务器加载文件,请求事件远远大于本机读取的时间,如果文件较多,网络迟缓就会导致页面瘫痪,所以浏览器更希望能够实现异步加载的方式。

    AMD规范则是异步加载模块,用于指定回调函数。等模块加载完成以后即可调用回调函数。AMD规范得意的产出就是require.js。

    https://requirejs.org/

    先通过示例来感受以下AMD规范实现的requirejs的应用:

    1.1定义工作区间文件结构

    1 cmd//工作区间
    2     modules-->依赖模块
    3         m1.js-->模块1
    4         m2.js-->模块2
    5     demo.html-->结构文本
    6     demo.js-->js主入口文件
    7     require.js-->CMD模块化工具

    1.2.1依赖模块代码(m1):

    1 define(function (){
    2    var name = 'm1-amd';
    3    function getName(){
    4        return name;
    5      }
    6      return {getName};//{getName}同等与{getName:getName} 
    7 })

    1.2.2依赖模块代码(m2):

    1 define(['m1'],function(m1){
    2     var msg = 'm2-amd';
    3     function show(){
    4         console.log(msg,m1.getName());
    5     }
    6     return {show};
    7 })

    1.3JS主入口文件:

     1 (function (){
     2     require.config({
     3         paths:{
     4             m2:'./modules/m2',
     5             m1:'./modules/m1'
     6         }
     7     });
     8     require(['m2','jquery'],function(m2,$){
     9         m2.show();
    10     });
    11 })();

    1.4在结构文本中引入AMD规范模块化处理工具require.js,并将主入口文件通过自定义属性data-main='主入口文件路径'的方式引入工具中进行处理:

    <script src="./require.js" data-main="./demo.js"></script>

    AMD的基本规范的全称“Asynchronous Module Definition”的缩写,意思是“异步加载模块”。它采用异步方式加载模块,模块的加载不影响后面语句的运行。所有依赖这个模块的语句,都定义在一个回调函数中,等到加载完成后,这个回调函数才会运行。

    AMD规范实际上是requirejs项目在推广过程中形成的一个产物,先来看看requirejs的基本使用:

      requirejs模块定义:define(id?,dependencies?,factory);==>id:可选参数,用来定义模块的标识,如果没有提供该参数,模块标识就取脚本文件名(去掉扩展名)。==>dependencies:用来传入当前模块依赖的模块名称数组。==>factory:工厂方法,模块初始化要执行的函数或对象,如果是函数,它只被执行一次。如果是对象,此对象应该为模块的输出值。

      requirejs模块主入口(模块加载):require.config({paths:{foo:'路径'}});==>faths:配置所有依赖模块的路径。在路径配置代码的下方,再通过require(dependencies?,factory)定义主入口文件的依赖关系和回调函数。

    在requirejs中还可以实现依赖其他库和插件,有些插件和库定义了requirejs的标准接口,比如jQuery,但是有些没有标准接口,requirejs官方都给出解决方案,可以参考这篇博客:https://www.cnblogs.com/goloving/p/7711104.html。例如我在示例中也测试了jQuery的使用:

     1 (function (){
     2     require.config({
     3         paths:{
     4             m2:'./modules/m2',
     5             m1:'./modules/m1',
     6             jquery:'./jquery-2.0.3'
     7         }
     8     });
     9     require(['m2','jquery'],function(m2,$){
    10         m2.show();
    11         $('body').css('backgroundColor','#000');
    12     });
    13 })();

    关于requirejs更多API可以查看官网的API示例:https://requirejs.org/docs/api.html

     二、CMD

     在上面一节介绍了AMD规范以及规范实现的requirejs的基本使用,其中提到了AMD相对于Commonjs的优势在于异步加载模块,但是我没由说明这个异步加载在什么时候触发,到了CMD这里有必要提一下了,AMD规范很重要的一个思想就是依赖前置,意思就是在模块执行前将所有依赖的模块先全部加载到本地。而CMD的加载方式也是异步加载,但是触发加载的时间是在需要某个依赖模块时再去加载,也有人将CMD说成是同步的,这种同步并不是表现在资源加载上,而是触发加载的指令与代码执行是同步的,资源加载还是异步加载模式。

    关于Commonjs、AMD、CMD、ES6模块化的异同在最后会由详细的对比分析。

    2.1.先来看CMD的基本应用:https://www.zhangxinxu.com/sp/seajs/

    2.1.1.定义工作区间文件结构

    CMD//工作区间
        -->modules//依赖模块
            -->m1.js
            -->m2.js
            -->m3.js
            -->m4.js
        dome.html//结构文本
        demo.js//JS主入入口文件
        sea.js//模块化工具

    2.1.2.m1模块代码

    1 define(function(require,exports,module){
    2     var msg = 'm1';
    3     function foo(){
    4         console.log(msg);
    5     }
    6     module.exports = {
    7         foo:foo
    8     }
    9 })

    2.1.3.m2模块代码

    1 define(function(require,exports,module){
    2     var msg = 'm2';
    3     function bar(){
    4         console.log(msg);
    5     }
    6     module.exports = bar;
    7 })

    2.1.4.m3模块代码

    1 define(function(require,exports,module){
    2     var msg = 'm3';
    3     function foo(){
    4         console.log(msg);
    5     }
    6     exports.foo = foo;
    7 })

    2.1.5.m4模块代码

     1 define(function(require,exports,module){
     2     var msg = 'm4';
     3     // 同步加载
     4     var m2 = require('./m2');
     5     m2();
     6     // 异步加载
     7     require.async('./m3',function(m3){
     8         m3.foo();
     9     });
    10     function fun(){
    11         console.log(msg);
    12     }
    13     exports.fun = fun;
    14 })

    2.1.6.JS主入口文件demo代码

    1 define(function(require,exports,module){
    2     var m1 = require('./modules/m1');
    3     m1.foo();
    4     var m4 = require('./modules/m4');
    5     m4.fun();
    6 })

    2.1.7.结构文本demo.html引入模块化处理工具sea.js,使用seajs工具对象方法user找到主入口文件并解析执行==>seajs.use('主入口文件路径'):

    1 <script src="./sea.js"></script>
    2 <script>
    3     seajs.use('./demo.js');
    4 </script>

    最后代码打印结果:

    这里值得我们关注的是m4打印在m3的前面,这就是CMD依赖就近原则产生的,在执行队列中异步请求需要等主线程执行完成以后才会调用执行,所以m3作为异步加载模块,在这个代码结构中要最后执行。

    值得我们注意的seajs也有同步加载模式直接使用require('模块路径')获取模块,异步模块加载方式需要使用require.async('模块路径',function(模块名称){回调执行内容})。

     三、ES6模块化

     ES6自带模块化,可以使用import关键字引入模块,通过export关键字到处模块,功能较之前几个方案更为强大,但是由于ES6目前无法在浏览器中执行,所以,需要通过babel将不支持的import编译为当前收到广泛支持的require。

     1 //  引入默认变量及方法和模块导入的m1 m2变量或方法
     2 import theDefault,{m1,m2} from 'lib';
     3 //  引入默认变量及方法
     4 import theDefault from 'lib';
     5 //  引入模块导出的m1 m2变量或方法
     6 import {m1,m2} from 'lib';
     7 //  引入模块导出的m1并且将m1重命名myName m2变量或者方法
     8 import * as myLib from 'lib';
     9 // 只将lib加载进来 没有用来lib中暴露的接口
    10 import 'lib';
    11 
    12 
    13 //  暴露变量
    14 export var a = '123';
    15 //  暴露函数
    16 export function myFun(){
    17 
    18 }
    19 //  默认暴露变量函数等
    20 export default a = '123';
    21 export function myFun(){}

    关于ES6的模块化会在ES6的相关博客中来详细解析,这里只做一些基本介绍。

     四、各个模块化规范对比理解

    1.什么是模块化?

    答:模块化是指将一个复杂的系统分解为多个模块,方便编码。

    2.为什么要用模块化?

    答:降低复杂性,降低代码耦合度,部署方便,提高效率。

    3.模块化的好处?

    答:3.1.避免命名冲突,减少变量空间污染;

      3.2.更好的分离代码,按序加载;

      3.3.更高复用性;

      3.4.更高可维护性;

    4.Webpack支持性:

    AMD、ES Modules(推荐使用)、CommonJS因为webpack是基于nodeJS的,所以有必要了解学习。

    5.AMD、CMD、CommonJS模块规范的对比分析:

      AMD、CMD可以使用插件引入的方式实现JS代码模块化管理,CommonJS不兼容浏览器需要Browserify工具在nodejs环境下转换成浏览器可执行的JS文件。

      Commonjs采用同步加载,会在一定程度上增加页面载入时间,如果在这个过程中出现某个模块错误,会导致页面加载失败。

      AMD、CMD采用异步加载,两者的区别就是AMD采用前置预加载模式,CMD采用就近原则加载模式。AMD的体验更好,CMD的性能更优,但是CMD需要考虑异步队列的执行顺序问题,所以这里的更好和更优要相对而言。

      (后续深入研究后再来补充)

  • 相关阅读:
    striding layers 是什么意思?
    faster rcnn算法及源码及论文解析相关博客
    地铁客流中样本问题
    numpy
    Softmax 函数的特点和作用是什么?
    Faster RCNN代码理解(Python)
    卷积神经网络(CNN)学习笔记1:基础入门
    semantic segmentation 和instance segmentation
    基于深度学习的目标检测
    全卷积网络 FCN 详解
  • 原文地址:https://www.cnblogs.com/ZheOneAndOnly/p/11075102.html
Copyright © 2011-2022 走看看