模块化-CMJ&ESM

CommonJS 重点

AMD

CMD

ES6 模块化 重点

每个模块尽量简洁,不超过50行代码,便于维护和复用,避免全局污染

nodejs直接运行某个js文件,该文件被称之为入口文件;

nodejs 遵循es标准,单由于脱离了浏览器环境,因此:

1、你可以在nodejs中使用es标准的任何语法或api,例如:循环、判断、数组、对象等

2、你不能在nodejs中使用浏览器的web api,例如:dom对象,window对象,document对象等

模块:模块就是一个js文件,它实现了一部分功能,并隐藏自己的内部实现,同时提供了一些接口供其他模块使用

模块有两个核心要素:隐藏和暴露

隐藏的是自己内部的实现

暴露的是希望外部使用的接口

任何一个正常的模块化标准,都应该默认隐藏模块中的所有实现,而通过一些语法或api调用来暴露接口

暴露接口的过程即模块的导出

当通过某种语法或api去使用一个模板时,这个过程叫做模块的导入 

CommonJS规范(静态依赖)

commonjs使用exports导出模块,require导入模块

nodejs中导入模块,使用相对路径,并且必须使用./或../开头

CMJ 具体规范如下:

1、如果一个js文件中存在exports或require,该文件是一个模块

2、模块内的所有代码均为隐藏代码,包括全局变量、全局函数,这些全局的内容均不应该对全局变量造成任何污染

3、如果一个模块需要暴露一些API提供给外部使用,需要通过exports导出,exports是一个空的对象,你可以为该对象添加任何需要导出的内容

4、如果一个模块需要导入其他模块,通过require实现,require是一个函数,传入模块的路径即可返回该模块导出的整个内容

nodejs对commonjs的实现:

1、为了保证高效的执行,仅加载必要的模块,nodejs只有执行到require函数时才会加载并执行模块

2、为了隐藏模块中的代码,nodejs执行模块时,会将模块中的所有代码放置到一个函数中执行,以保证不污染全局变量

(function(){//模块中的代码})()

3、为了保证顺利的导出模块内容,nodejs做了一下处理

1)在模块开始执行前,初始化一个值module.exports={}

2)module.exports即模块的导出值

3)为了方便开发者便捷的导出,nodejs在初始化module.exports后,又声明了一个变量exports=module.exports,在exports中加属性,然后进行导出

(function(module){

     module.exports = {};

    var exports = module.exports;

   //模块中的代码

   return module.exports;

})()

4)为了避免反复加载同一个模块,nodejs默认开启了模块缓存,如果加载的模块已经被加载过了,则会自动使用之前的导出结果

commonjs是同步的

不能在浏览器运行的原因:

1、远程加载js浪费时间

2、模块代码需要放到函数中执行

要解决这两个问题,出现了AMD和CMD

AMD全称是Asynchronous Module Definition 即异步模块加载机制

require.js实现了AMD规范,在AMD中,导入和导出模块的代码,都必须放置在define函数中

define([依赖的模块列表],function(模块名列表){

//模块内部的代码

return导出的内容

})

CMD全称是COMMON Module Definition 公共模块定义规范

sea.js实现了CMD规范

在cmd中,导入和导出模块的代码,必须放置在define函数中

define((require,exports,module)=>{

  //模块内部代码

})

Commonjs依赖延迟声明:

优点:某些时候可以提高效率

缺点:无法在一开始确定模块依赖关系

ES6模块化(ESM)的特点

:(动态依赖、静态依赖)

1、使用依赖 预声明 的方式导入模块

2、灵活的多种导入导出方式

3、规范的路径表示法:所有路径必须以./或../开头

模块的引入,注意:这一部分非模块化

目前,浏览器使用以下方式引入一个ES6模块文件:

<script src= "入口文件" type="module">

ES6的模块导入导出分为两种:

1、基本导入导出

导出:(由于基本导出必须具有名称,所以要求导出内容必须跟上声明表达式或具名符号)

export 基本声明表达式

(export var a =1)

或 export {具名符号}

(var age = 18;

export{age}; )

导入:(由于使用的是预依赖加载,因此导入其他任何模块,都需要写在所有代码之前)

import{导出的符号列表} from "模块路径"

导入细节:

1)导入时,可以通过关键字as对导入的符号进行重新命名

import{b as c} from "模块路径"

2)导入时使用的符号是常量,不可修改

3)可以使用*号导入所有的基本导出,行成一个对象

import * as d  from "模块路径"

4)有一些初始化代码,只需要导入,不需要运行,可以直接写代码:

import    "模块路径"

2、默认导入导出

每个模块,除了允许有多个基本导出之外,还允许有一个默认导出,由于只有一个,因此无需取名,每个模块不能出现多个默认导出语句

默认导出:

export default 默认导出的数据

或 export{默认导出的数据 as default}

默认导入:

import 接收变量名 from “模块路径”

如果希望同时导入某个模块的默认导出和基本导出,可以使用下面的语法:

import 接收默认导出的变量,{接收基本导出的变量} from “模块路径”

如果使用*号,会将模块的所有默认导出和基本导出聚合到一个对象中,默认导出会作为属性default存在

以上均为静态导入

1、静态导入的代码必须在代码顶端,也不可放在代码块中

2、静态导入的代码绑定的符号是常量,不可更改

动态导入:

import("模块路径")

返回一个promise,完成时的数据为模块对象

ES6模块化细节:

1、尽量导出不可变值

2、可以使用无绑定的导入用于执行一些初始化代码;import    "模块路径"

3、可以使用绑定再导出,来重新导出来自另一个模块的内容

export (绑定的标识符) from "模块路径"

猜你喜欢

转载自blog.csdn.net/qinqinzqq/article/details/125429415