模块化开发要解决的问题:
1.冲突
比如:多人协作开发时,不同js库中的函数重名问题
可以用命名空间解决:
var module={}
module.a=1;
module.b=function(){}
...
命名空间的缺点:
1)写起来较为复杂(特别是涉及到多级命名空间时)
2)只能减少冲突,不能完全消除冲突(两个开发人员恰巧用了同名的命名空间)
2.依赖
引入了多个存在依赖关系js库,后期维护不断增删js库,导致混乱,出现问题
3.SeaJs(CMD规范,在commonJS(服务端模块化规范)基础上)
解决冲突与依赖,便于维护
不同于jq库参与实际开发过程,它不涉及逻辑,相当于“后勤”。
4.SeaJs模块化开发的步骤
step1:引入seajs文件,方法同普通js文件
step2:如何形成模块——用define函数包含模块(定义模块),define有三个参数:require,exports,module.它们类似关键字,不可更改
step3:如何调用模块——exports给外部提供接口;seajs.use(url,callback)引入被调用的模块(加载模块)。回调函数会返回一个参数,也即exports
step4:多个模块如何实现相互依赖?——require(url)函数,获取指定模块的接口,也即exports,这样便可获得指定模块内的变量或函数(前提是该模块提供了变量或函数的外部接口exports)
5.实际用法举例
页面调用模块:
//index.html
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>seajs</title>
<script src="sea.js"></script>
</head>
<body>
<script>
seajs.use("./modules/module1.js",function(ex){
ex.show();
})
</script>
</body>
</html> //module1.js
define(function(require,exports,module){
function show(){
alert("我是module1的show函数");
}
exports.show=show;
})
模块间相互依赖1(依赖的是普通js文件):
//index.html
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>seajs</title>
<script src="sea.js"></script>
</head>
<body>
<script>
seajs.use("./modules/module1.js",function(ex){
ex.show();
})
</script>
</body>
</html> //module1.js
define(function(require,exports,module){
require("./normal.js");
function show(){
alert(a);
}
exports.show=show;
}) //normal.js
var a=100;
模块间相互依赖2(依赖的也是seajs模块文件):
//index.html
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>seajs</title>
<script src="sea.js"></script>
</head>
<body>
<script>
seajs.use("./modules/module1.js",function(ex){
ex.show();
})
</script>
</body>
</html> //module1.js
define(function(require,exports,module){
var a=require("./module2.js").a; //require返回值相当于exports
function show(){
alert(a);
}
exports.show=show;
}) //module2.js
define(function(require,exports,module){
var a=100;
exports.a=a;//因为是模块,所以必须提供对外接口
})
6.seaJs配置
alias 别名配置
当模块标识很长时,可以使用 alias
来简化。
seajs.config({
alias: {
'jquery': 'jquery/jquery/1.10.1/jquery',
'app/biz': 'http://path/to/app/biz.js',
}
});
paths
当目录比较深,或需要跨目录调用模块时,可以使用 paths
来简化书写。
seajs.config({
paths: {
'gallery': 'https://a.alipayobjects.com/gallery',
'app': 'path/to/app',
}
});
与别名配置合用,可以简化路径书写
更多配置参数见seaJs配置
7.第三个参数module
module.id:模块唯一标识
module.uri:模块绝对路径
module.dependencies:该模块所依赖的模块数组
module.exports:
exports是module.exports的引用,它们是两个不同的对象,但是引用关系
我们真正调用的对象是module.exports
当要对模块的对外接口进行修改时,只能用module.exports,一般情况下用exports
8.require.async() 异步加载模块
require.async(“./module1.js”,callback) ;
//不需要等module1加载完成,下面的代码就可以执行
var a=100;
blablabla...
9.插件
1.安装spm
2.seaJs插件
10.技巧
1.通过seajs.use()一次引入多个模块:
seajs.use(["./module1.js","module2.js"],function(ex1,ex2){
ex1.show();
ex2.show();
})
2.性能
为了让 sea.js
内部能快速获取到自身路径,推荐手动加上 id
属性:
<script src="path/to/sea.js" id="seajsnode"></script>
加上 seajsnode
值,可以让 sea.js
直接获取到自身路径,而不需要通过其他机制去自动获取。这对性能和稳定性会有一定提升,推荐默认都加上。
3.线上调试
控制台:seajs.cache