为什么要使用模块化
目的:
- 解决命名冲突的问题
- 解决依赖管理的问题
- 使代码的可读性更高
- 代码解耦提高复用性
CMD、AMD、CommonJS 规范分别指什么?有哪些应用
CommonJS 规范
CommonJS 规范规定,每个文件就是一个模块,有自己的作用域。在一个文件里面定义的变量、函数、类,都是私有的,对其他文件不可见。
//math.js
var x = 5;
var addX = function (value) {
return value + x;
};
module.exports.x = x;
module.exports.addX = addX;
//math.js
var math= require('./math.js');
console.log(math.x)//5
console.log(math.addX)//6
其中module
变量代表当前模块,这个变量是一个对象,它的exports
属性是对外的接口。加载某个模块时其实是加载该模块的module.exports
,require
方法用于加载该模块
AMD规范
AMD是Asynchronous Module Definition
的简写,意思就是"异步模块定义"。是 RequireJS 在推广过程中的规范化产出。
requireJS定义了一个函数 define
,它是全局变量,用来定义模块
语法:define(id?, dependencies?, factory);
- id:可选参数,用来定义模块的标识,如果没有提供该参数,脚本文件名(去掉拓展名)
- dependencies:是一个当前模块依赖的模块名称数组
- factory:工厂方法,模块初始化要执行的函数或对象。如果为函数,它应该只被执行一次。如果是对象,此对象应该为模块的输出值。
在页面上使用require函数加载模块
require([dependencies], function(){});
require()
函数接受两个参数
- 第一个参数是一个数组,表示所依赖的模块
- 第二个参数是一个回调函数,当前面指定的模块都加载成功后,它将被调用。加载的模块会以参数形式传入该函数,从而在回调函数内部就可以使用这些模块
require()
函数在加载依赖的函数的时候是异步加载的,这样浏览器不会失去响应,它指定的回调函数,只有前面的模块都加载成功后,才会运行,解决了依赖性的问题。
CMD
CMD是Common Moudle Definition
的缩写,意思就是通用模块定义,这个规范是Sea.js
推广过程中产生的,Sea.js
要解决的问题和requireJS
一样,只不过在模块定义方式和模块加载(可以说运行、解析)时机上有所不同
语法:define(id?, deps?, factory)
工厂函数中有require, exports, module
三个参数
require
是接受其他模块方法,exports
是模块提供给外部调用的api,module
储存模块的一些信息
// 定义模块 myModule.js
define(function(require, exports, module) {
var $ = require('jquery.js')
$('div').addClass('active');
});
// 加载模块
seajs.use(['myModule.js'], function(my){
});
AMD和CMD的区别
普通的区别:
- AMD推崇依赖前置,在定义模块的时候就要声明其依赖的模块
- CMD推崇就近依赖,只有在用到某个模块的时候再去require
这种区别各有优劣,只是语法上的差别。
他们最大的区别是对依赖模块的执行时机不同:
- AMD在加载模块完成后就会执行该模块,所有模块都加载执行完后会进入require的回调函数,执行主逻辑,这样的效果就是依赖模块的执行顺序和书写顺序不一定一致,看网络速度,哪个先下载下来,哪个先执行,但是主逻辑一定在所有依赖加载完成后才执行。
- CMD加载完某个依赖模块后并不执行,只是下载而已,在所有依赖模块加载完成后进入主逻辑,遇到require语句的时候才执行对应的模块。
应用:
- CommonJS 适用于服务端,基于 Node,可用 Glup、 Webpack 之类的打包压缩再用于浏览器环境。
- AMD 用于浏览器环境,如 RequireJS
- CMD 用于浏览器环境, SeaJS 推广中产出
使用 requirejs 完善以下功能
1. 首屏大图为全屏轮播
2. 有回到顶部功能
3. 图片区使用瀑布流布局(图片高度不一),下部有加载更多按钮,点击加载更多会加载更多数据(数据在后端 mock)
4. 使用 r.js 打包应用