模块化之AMD,CMD,CommonJs,ES6 Module

文章目录

      • 一.简介
      • 二.AMD(异步模块定义)
        • 1.AMD原理
        • 2.为什么要使用require.js
        • 3.require.js的使用
          • 1.require加载模块
          • 2.require.config()
          • 3.require.config()全局配置
          • 4.define
          • 5.完整示例
      • 三.CMD(通用模块定义)
        • 1.CMD原理
        • 2.为什么要使用seajs
        • 3.seajs的使用
          • 1.define
          • 2.seajs.config()
          • 3.seajs.use()加载模块
          • 4.完整示例
      • 四.CommonJS
        • 1.CommonJS原理
      • 五.ES6模块系统
        • 1.ES5的浏览器加载规则
          • 1.defer和async
          • 2.defer和async区别
        • 2.ES6的浏览器加载
          • 1.es6 引入外部js
          • 2.es6 网页模块写法
          • 3.ES6引入外部模块注意事项
      • 六.AMD,CMD,CommonJS,ES6 Module区别
        • 1.AMD,CMD对比
          • 1.相同点
          • 2.不同点
        • 2.AMD,CMD与CommonJs与ES6 Module对比
          • 1.相同点
          • 2.不同点

一.简介

AMD、CMD、CommonJsES5中提供的模块化编程的方案,ES6 module的import/exportES6中定义新增的

ES6之前,社区指定了一些模块加载方案,最主要的有 CommonJS 和 AMD 两种。前者用于服务器,后者用于浏览器,ES6之后,实现了模块功能,而且实现相当简单,完全可以取代CommonJS和AMD规范,成为浏览器和服务器通用的模块解决方案。

模块化:就是将不同的功能的函数按模块封装起来,并提供使用接口,他们彼此之间互不影响,一个模块就是一个文件

二.AMD(异步模块定义)

AMD规范是RequireJS在推广过程中对模块定义的规范化产出,它是一个概念,RequireJS是对这个概念的实现.AMD是一个组织,RequireJS是在这个组织下自定义的一套脚本语言.

1.AMD原理

AMD规范采用的是异步的模块加载机制,它的加载不影响后面文件的加载,所有依赖这个模块的语句都放在一个回调函数里,等到所有都加载完成,才执行这个回调函数.

AMD是在require.js推广过程的产物,推崇依赖前置,提前执行.即使没有用到的模块,也提前加载,require.js采用require.config()定义模块路径,define()定义依赖模块,使用require加载模块

2.为什么要使用require.js

以前我们开发一个网页,会把一个网页上所有需要的js放上面,看上去既臃肿又复杂,这种通过script标签来导入一个个的js文件这种方式已经不能满足现状互联网开发模式,我们需要团队协作,模块复用,单元测试,等一系列复杂的需求.

require.js 会在相关的js加载后执行回调函数,这个过程是异步的,所以可以防止js加载阻塞页面渲染

使用程序调用的方式加载js,防出现如下丑陋的场景:
模块化之AMD,CMD,CommonJs,ES6 Module_第1张图片

3.require.js的使用

一个模块就是一个文件

1.require加载模块

require用来加载依赖模块,并执行加载完后的回调函数

(1) 第一个参数是依赖模块列表

(2) 第二个参数是一个callback函数

2.require.config()

用来配置模块加载位置,简单点说就是引入模块并起一个别名

比如将百度的jquery库地址标记为jquery,这样在require时只需要写[“jquery”]就可以加载该js本地的js模块我们也可以这样配置

3.require.config()全局配置

我们不可能每个页面都重复配置require.config,如果每个页面都加入这样的配置,那肯定不好看,所以require.js提供了一种叫"主数据"的功能

(1)首先,我们在项目中创建一个main.js,作为主入口文件,在main.js里进行require.config的配置

(2)然后我们在页面中使用下面的方式来使用require.js

/** 网页中引入require.js及index.main.js **/
<script src="js/require.js" async="true" defer data-main="js/index.main.js"></script>

加载require.js的script标签加入了data-main属性(设置入口文件),这个属性指定的js将在require.js加载完成后处理,我们把require.config的配置加入到data-main后,就可以使每个页面都使用这种配置,然后页面中就可以直接用require来加载所有的短路径模块名

4.define

用来定义一个模块

//第一种方式
define({
  //key:value
})
//第二种方式
define(function(){
    return {
        
    }
});
//第三种方式(推荐使用此种方式)
define(['依赖的模块路径'],function(依赖模块名称或别名){
    return{
        
    }
});
//第四种方式(官方不推荐)
define('模块名称', ['依赖的模块路径'], function(依赖模块名称){// 官方不推荐
 // ...
 return {
  // ...
 };
});

推荐使用第三种方式

5.完整示例
/** 网页中引入require.js及index.main.js **/


/** index.main.js 入口文件 **/
//使用config()方法配置路径地址
require.config({
    baseUrl: "js/lib",
    paths: {
      "jquery": ["http://libs.baidu.com/jquery/2.0.3/jquery","jquery-1.10.1.min"],//全路径
      "cookie": "jquery.cookie",
      "details": "details",//实际路径为js/lib/details.js
      "banner": "banner"
    },
    shim: {
        //设置依赖关系
        "cookie": ["jquery"]
      
    }
});

//引入模块,调用执行 (require用来加载依赖模块,并执行加载完后的回调函数)
require(["details", "banner"], function (details, banner) {
    details.init();
});


/** 主功能模块的实现 details.js **/
//u,$ 为当前引入的模块起的别名
define(['urlParm', "jquery", "cookie"], function (u, $) {
	//实现功能
});

三.CMD(通用模块定义)

CMD规范SeaJS在推广过程中对模块定义的规范化产出,是一个同步模块定义但是它是异步加载的,是SeaJS的一个标准,SeaJSCMD概念的一个实现,SeaJS是淘宝团队提供的一个模块开发的js框架

1.CMD原理

CMD规范AMD规范一样,也是并行加载所有依赖的模块,但是不会立即执行模块,等到真正需要(require)的时候,才开始解析,也就是说,CMD是延迟执行的,也就是懒执行

SeaJSCMD概念的一个实现,推崇依赖就近,延迟执行

/** CMD写法 **/
define(function(require, exports, module) {
    var a = require('./a'); //在需要时申明
    a.doSomething();
    if (false) {
        var b = require('./b');
        b.doSomething();
    }
});

2.为什么要使用seajs

require.js一样,同样也是为了解决文件之间依赖问题,防止js加载阻塞页面渲染

3.seajs的使用

1.define

是一个全局函数,用来定义模块

define接收一个参数,参数可以是函数,也可以是对象,也可以是字符串,下面讲的是参数为函数时

define(function(require, exports, module) {
  // 模块代码
});

define中参数为函数时,表示是模块的构造方法,执行该构造方法,可以得到模块向外提供的接口,该构造方法接收3个参数requireexportsmodule

(1) require 是一个方法,用来接受模块标识(模块路径)作为唯一参数,用来获取其他模块提供的接口

define(function(require, exports) {
  // 获取模块 a 的接口
  var a = require('./a');
  // 调用模块 a 的方法
  a.doSomething();
});

(2)exports 是一个对象,用来向外提供模块接口

define(function(require, exports) {
  // 对外提供 foo 属性
  exports.foo = 'bar';
  // 对外提供 doSomething 方法
  exports.doSomething = function() {};
});

(3)module 是一个对象,上面存储了与当前模块相关联的一些属性和方法.一般会使用module.exports来给当前模块对外提供接口

define(function (require, exports, module) {
    //依赖encrypt.js,用户名,密码加密
    require('headhunt-encrypt');

    module.exports = {
        Init: function () {
            Register.ChangeValidateCode("ImgCode", Register.imgSrc);
            Register.TextHanlder();
        }
    }
});
2.seajs.config()

全局配置需要加载的模块

seajs.config({
    // 基础路径
    base: 'http://js.cjolimg.com',
    // 路径配置
    paths: {
        "JsCommonHost": "v8/plugins",
    },
    // 别名配置
    alias: {
        "jquery": "v8/jquery-1.8.3.min",
        "layer": "JsCommonHost/layer/layer",
    }
});
3.seajs.use()加载模块
// 加载模块
seajs.use(['jquery.js'], function(math){
    //
});
4.完整示例
/** sea.js **/
// 定义模块 math.js
define(function(require, exports, module) {
    var $ = require('jquery.js');
    var add = function(a,b){
        return a+b;
    }
    exports.add = add;
});
// 加载模块
seajs.use(['math.js'], function(math){
    var sum = math.add(1+2);
});

四.CommonJS

CommonJs规范最典型的代表:Nodejs,它有四个重要的环境变量为模块化提供支持.module,export,require,global,在实际使用中,使用module.exports定义当前模块对外输出接口,用require来加载模块

commonJS的相关详情,我之前的一篇博客有写,请移步CommonJS规范

// 定义模块math.js
var basicNum = 0;
function add(a, b) {
  return a + b;
}
module.exports = { //在这里写上需要向外暴露的函数、变量
  add: add,
  basicNum: basicNum
}

// 引用自定义的模块时,参数包含路径,可省略.js
var math = require('./math');
math.add(2, 5);

// 引用核心模块时,不需要带路径
var http = require('http');
http.createService(...).listen(3000);

CommonJS规范,对外输出模块的方式有两种

(1) module.exports 当前模块对外输出的接口

(2) exports 每个模块化还提供一个exports变量,指向module.exports

1.CommonJS原理

CommonJs采用同步的方式进行加载模块,用于服务端,在服务端,模块文件存储在本地磁盘,读取很快,所以这样不会问他,但是在浏览器中,由于网络等原因,更合理的方法是异步加载

五.ES6模块系统

ES6在语言标准层面上,实现了模块功能,意在实现服务器端和浏览器端统一的模块解决方案,ES6的模块系统,主要由2个命令构成,export和import,export规范对外的接口,import引用其他的模块功能,ES6模块不是对象,import命令在编译时引用模块,而不是在运行时.

/** 定义模块 math.js **/
var basicNum = 0;
var add = function (a, b) {
    return a + b;
};
export { basicNum, add };

/** 引用模块 **/
import { basicNum, add } from './math';
function test(ele) {
    ele.textContent = add(99 + basicNum);
}

服务端和浏览器端都适用

1.ES5的浏览器加载规则

默认情况下,浏览器是同步加载JavaScript脚本,即渲染引擎遇到

你可能感兴趣的:(JavaScript)