1.概述

什么是模块化?

  模块化就是把系统分离成独立功能个方法,需要什么功能,就加载什么功能;

优点:

  解决传统编码过程中的命名冲突和文件依赖的问题;

  提高代码的可维护性,可复用性以及提高生产效率。

CommonJs

common.js主要用于服务器端;

common.js加载模块是同步的,也就是说,加载完成之后执行后面的操作;

commonJs使用基于文件的模块,所以一每个文件只能定义一个模块;

Node.js主要用于服务端编程,模块都是存储在本地的硬盘中加载比较快,所以Node.js采用的是common.js的规范;

common.js规范分为三个部分:

module(模块标识):module变量在每个模块的内部,就代表当前模块

require(模块引用):require()用来加载外部模块,读取并执行js文件,返回该模块的exports对象;

exports(模块输出):exports是对外的接口,用于导出当前模块的变量和方法;

// aModule.js
const $ = require("jQuery");     // 用于其他的模块
let count = 1;
const numClick = function(){
    alert(++count)
}

module.exports = {                 // 使用module.exports 定义模块公共接口
     countClick:function(){
           $(document).on("click",numClick )
    }
}

//使用我们写的module
const aModule = require("aModule");  //引入模块

aModule.countClick();     //使用定义的公共接口

我们需要注意的是:虽然我们的在aModule.js中定义的 "全局变量" $ , count, numClick;在我们的标准js文件中会生成全局变量,但是在Commonjs中它的作用域只存在于当前的模块;

AMD(require.js) 主要用于浏览器端;

AMD就是异步模块定义。它采用异步的方法加载模块,通过define方法去定义模块,require方法去加载模块 ;

AMD模块定义
如果这个模块还依赖于其他模块,那么define函数的第一个参数,必须是一个数组,指明该模块的依赖;

define(["tool"],function(){
// 模块逻辑
}}))

  

// AMD模块的加载
require(['modules'],callback);

// 第一个参数 ['modules'] ,是一个数组,里面的成员就是要加载的模块;
// 第二个参数 callback ,则是加载成功之后的回调函数。

require异步加载模块,浏览器在加载过程中不会失去响应;指定的回调函数,只有在前面的模块加载成功后,才会去执行,解决了依赖性的问题。

// a.js 定义a 模块 依赖于b模块
define(["b"],function(){
    console.log(b)
    var hello = function(){
        console.log("hello")
    }
    return {
        hello:hello
    }
})

// b.js  定义b模块
define(function(){
    var name = "max";
    return {
        name : name
    }
})

  

demo.html
<script>
    require.config({   // 配置路径别名
        path : {
            'a':'./a',
            'b':'./b'
        }
    })
    require(['a','b'],function(a,b){    // 引入a,b模块
        console.log(a); // {hello:function(){}}
        console.log(b); // {name:'max'}
    })
</script>

 

CMD(sea.js)

CMD 即通用模块定义,CMD规范是国内发展过来的;Sea.js和 require.js解决的问题是一样的,只不过在模块的定义方法和加载方法不同。

CMD推崇就近依赖,延迟执行。文件时提前加载好的,只有在require的时候才去执行文件;

在CMD规范中,一个模块就是一个文件。

require 是可以把其他模块导进来的一个参数;
exports 可以把模块内的一些属性和方法导出;
module是一个对象,上面储存了与当前模块相关联的一下属性和方法;

define(function(require,exports,module){
    // 模块代码
})
a.js
define(function(require,exports,module){
    export.name = "max"
})
b.js
define(function(require,exports,module){
    var a = require('./a');
    export.hello = function(){
        console.log("hello")
    }
})
demo.html
<script>
    seajs.config({
        alias:{
            a:'./a',
            b:'./b'
        }
    })
    seajs.use(['a','b'],function(a,b){
        console.log(a);
        console.log(b);
    })
</script>

ES6模块化:

ES6汲取了Commonjs 和 AMD 的优点,语法简洁,并且基于文件。支持异步加载,未来可以成为浏览器和服务端通用的模块化解决方案;
ES6的主要思想是必须显式的使用标识符导出模块,才能从外部访问模块。其他的标识符,甚至在顶级的顶级作用域中定义,也只能在模块内使用;(与CommonJs一样)

ES6提供了两个标识符:

  import:导入模块标识符
  export:从模块外部指定标识符(用于把模块中的内容暴露出来)
 
ES6的导出模式分以下几种:
1.使用关键字export分被导出定义的变量和函数
export const name = 'hyh';
export function compare(){};
export class Car()
2.使用export将所有的模块标识符全部导出
 const name = 'hyh';
 function compare(){};
 class Car()
export { name, compare }
3.使用expport default 关键字定义模块的默认导出
export default class Car()
4.使用默认导出的同时还可以导出指定的名称
export default class Car();
export const name = "hyh"
5.通过关键字 as 设置别名
const name = "hyh"
export { name as myname }
 
ES6的引入模式
1.导入默认的导出
import car from 'aModule.js'
2.导入命名导出
import { name, compare } from 'aModule.js'
3.导入模块中声明的全部导出内容
import * as aModule from 'aModule.js'
4.通过别名导入模块中声明的全部导出内容
import {name as myname} from 'aModule.js'
5.导入默认导出和命名导出
import car,{name,compare} from 'aModule.js'
export 与 export default 的区别
导入模块默认导出的内容,不需要使用花括号{},可以任意指定名称
导入已命名的导出内容必须使用花括号,且名称需要对应