为什么要使用模块化?
- 解决命名冲突
- 文件依赖的管理
- 提高代码可读性
- 代码解耦,提高复用性
CMD、AMD、CommonJS 规范分别指什么?有哪些应用
CommonJS服务器端规范(node.js使用)
node.js 天然支持CommonJS规范
- 定义模块 ,根据CommonJS规范,一个单独的文件就是一个模块,每一个模块都是一个单独的作用域,在一个模块定义的变量无法被其他模块读取,除非定义为global对象的属性。
- 模块输出:模块只有一个出口,module.exprots 对象,我们需要把模块希望输出的内容放在该对象里面。
- 加载模块:加载模块使用require方法,该方法读取一个文件并执行,返回文件内部的modul.exports对象。
|
|
缺陷:
require是同步的。即模块系统需要同步读取文件内容,并编译执行已得到模块接口。这在服务器端实现很简单,在浏览器端,加载JavaScript最佳方式是document中插入script标签。但是脚本标签天生异步,所以,传统CommonJS模块在浏览器环境中无法正常加载。
AMD (Asynchronous Module Definition, 异步模块定义)
指定一种机制,在该机制下模块和依赖可以移步加载。这对浏览器端的异步加载尤其适用。由于不是JavaScript原生支持,使用AMD规范进行页面开发需要用到对应的库函数RequireJS。实现AMD的库有`RequireJS 、curl 、Dojo 等。
RequireJS主要解决的问题
- 当多个js文件可能有依赖关系,被依赖的文件需要早于依赖它的文件加载。
- js加载时浏览器会停止页面渲染,加载文件越多,页面失去响应时间越长。
define函数,用来定义模块
|
|
- id :可选参数,用来定义模块标识,如果没有提供该参数,脚本的文件名(去掉后缀)
- dependencies:是一个当前模块依赖的模块名称数组
- factory:方法,模块初始化要执行的函数或对象。如果为函数,它应该只被执行一次。如果是对象,此对象应该为模块的输出值
|
|
require()函数在加载依赖的函数的时候是异步加载的,这样浏览器不会失去响应,它指定的回调函数,只有前面的模块都加载成功后,才会运行,解决了依赖性的问题。
CMD( COMMON MModule Definition)
CMD有个浏览器的实现SeaJS,SeaJS要解决的问题和requireJS一样,只不过在模块定义方式和模块加载(可以说运行、解析)时机上有所不同
语法
Sea.js 推崇一个模块一个文件,遵循统一的写法
define用来定义模块
|
|
- CMD推崇用文件名作为模块id
- CMD推崇依赖就近,一般不在define的参数中写依赖,在factory中写
- factory有三个参数
|
|
AMD与CMD区别
最明显的区别:在模块定义时依赖的处理不同
- AMD推崇依赖前置,在定义模块的时候就要声明其依赖的模块
- CMD推崇就近依赖,只有在用到某个模块的时候再去require
这种区别各有优劣,只是语法上的差异,而且requireJS和seaJS都支持对方的写法。
最大的区别:对依赖模块的执行时机不同
- 同样是异步加载模块,AMD在加载模块完成之后就会执行该模块,所有模块都执行完就会进入require的回调函数,执行主逻辑,这样依赖模块的执行顺序和书写顺序不一定一致,看网络速度,哪个先下载下来,哪个先执行,但是主逻辑一定在所有依赖加载完成后才执行。
- CMD加载完一个依赖模块后并不执行,只是下载而已,在所有依赖模块加载完成之后进入主逻辑,遇到require语句时才执行对应的模块,这样模块的执行顺序和书写顺序是完全一致的
这也是很多人说AMD用户体验好,因为没有延迟,依赖模块提前执行了,CMD性能好,因为只有用户需要的时候才执行的原因
使用 requirejs 完善入门任务15,包括如下功能:
新闻加载需要server mock