JavaScript 模块化编程
JavaScript 模块化编程
exapmle:
var module1 = ( function($, YAHOO){
//...
})(jQuery, YAHOO);
模块规范: CommonJS 和 AMD
对于浏览器端的模块,只能采用“异步加载”。这就是AMD规范诞生的背景。
AMD: Asynchronous Module Definition
它采用异步方式加载模块,模块的加载不影响它后面语句的执行。所有依赖这个模块的语句,都定义在一个回调函数中,等到模块加载完成之后,这个回调函数才会执行。
写法如下:
require([module], callback);
第一个参数[module], 是一个数组,里面的成员是要加载的模块。
例如:
require(['math'], function(){
math.add(2, 3);
})
一个流行的库 require.js
解决两个问题:
- 实现js文件的异步加载,避免网页失去响应
- 管理模块之间的依赖性,便于代码的编写和维护
引入库文件:
使其异步加载,可以加入属性:async="true" (IE支持 defer)
引入require之后,加入我们自己的代码:
假定我们的文件是main.js,在js目录下。
data-main属性的作用是,指定网页程序的主模块。
如何写主模块main.js:
require(['moduleA', 'moduleB', 'moduleC'], function(moduleA, moduleB, moduleC){
// do something
});
一个实际的例子:
require(['jquery', 'underscore', 'backbone'], function($, _, Backbone){
//some code here
});
模块的加载:
默认情况下,require假定所要加载的模块与main.js在同一目录下。
使用require.config()方法,我们可以自定义模块的加载行为。require.config()就写在main.js的头部。参数是一个对象,对象的path属性指定各个模块的加载路径。
// 相同路径,指定模块的文件名
require.config({
paths: {
'jquery': 'jquery.min',
'underscore': 'underscore.min',
'backbone': 'backbone.min'
}
});
// 不同路径,指定路径及文件名
require.config({
paths: {
'jquery': 'lib/jquery.min',
...
}
});
// 或者指定基目录
require.config({
baseUrl: 'js/lib',
paths: {
'jquery': 'jquery.min',
...
}
});
// 也可以指定url
require.config({
paths: {
'jquery': 'https://ajax.../jquery.min',
...
}
});
模块的写法
如果一个模块不依赖其他模块,则直接定义一个模块:
// math.js
define(function() {
var add = function(x, y) {
return x + y;
};
return {
add: add
}
})
加载方法:
require(['math'], function(math) {
// ...
})
如果这个模块还以来其他模块,则define() 函数的第一个参数必须是一个数组,指明该模块的依赖性:
define(['myLib', function(mylib){
function foo(){
myLib.doSomething();
}
return {
foo: foo
};
}]);
加载非规范的模块:
比如underscore和backbone这两个库,都没有采用AMD规范编写。如果要加载他们的话,必须先定义他们的特征:
require.config({
shim: {
'underscore': {
exports: '_'
},
'backbone': {
deps: ['underscore', 'jquery'],
exports: 'Backbone'
}
}
});
shim属性专门用来配置不兼容的模块,每个模块要定义:
(1) exports值(输出的变量名),表明这个模块外部调用时的名称
(2) deps数组,表明该模块的依赖
比如:
shim: {
'jquery': {
deps: ['jquery'],
exports: 'jQuery.fn.scroll'
}
}
require.js 插件:
domready插件,可以让回调函数在DOM结构加载完成后再执行。
require(['domready!'], function(doc){
// called once the DOM is ready
});
text和image插件,允许require加载文本和图片文件:
define([
'text!review.text',
'image!cat.jpg'
],
function(review, cat) {
console.log(review);
document.body.appendChild(cat);
}
);