SeaJS是一个遵循CMD规范的JavaScript模块加载框架,可以实现JavaScript的模块化开发及加载机制。
为什么使用SeaJs?
SeaJS 追求简单、自然的代码书写和组织方式,具有以下核心特性:
简单友好的模块定义规范:SeaJS 遵循CMD规范,可以像Node.js一般书写模块代码。
自然直观的代码组织方式:依赖的自动加载、配置的简洁清晰,可以让我们更多地享受编码的乐趣。
SeaJS 还提供常用插件,非常有助于开发调试和性能优化,并具有丰富的可扩展接口。
SeaJS可运行在Mobile端,包括Hybrid模式的App上。理论上,SeaJs可运行在任何浏览器引擎上。
入门5分钟
在页面的页尾,通过script引入sea.js后,有一段配置代码。
//seajs.config({
//Seajs的基础路径
base:'../sea-modules/',
//设置别名,方便调用
alias:{
"jquery":'jquery/jquery/1.10.1/jquery.js'
}
})
//加载入口模块
seajs.use("../static/hello.js")
Seajs在下载完成后,会自动加载入口模块。页面中的代码就这么简单。
//所有模块都通过define定义
define(function(require,exports,module){
//通过require引入依赖
var $=require("jquery")
//通过exports对外提供接口
exports.doSomething=...
//或者通过module.exports 提供整个接口
module.exports=..
})
API快速参考
seajs.config
用于对sea.js进行配置。
seajs.config({
//设置路径,方便跨目录调用
paths:{
'jquery':'../jquery'
},
//设置别名,方便调用
alias:{
'class':'class/1.0.0/class'
},
//变量配置
vars:{
'name':'scott'
},
//预加载项
preload:[
this.JSON?'':'json'
],
charset:'utf-8'
})
alias 与path的区别?
path:当目录比较深,或者需要跨目录调用模块时,可以使用paths简化。
alias:可以让文件的真实路径与调用标识分开,有利于统一维护。
seajs.use
用来在页面中加载一个或多个模块
// 加载一个模块
seajs.use('./a');
// 加载一个模块,在加载完成时,执行回调
seajs.use('./a', function(a) {
a.doSomething();
});
// 加载多个模块,在加载完成时,执行回调
seajs.use(['./a', './b'], function(a, b) {
a.doSomething();
b.doSomething();
});
1 seajs.use理论上只用于加载驱动,不应该出现在define中的模块代码里。在模块代码里需要异步加载其他模块时,推荐使用require.async方法。
2 seajs.use与DOM ready事件没有任何关系。若某些操作要确保在DOM ready后执行,需要使用jquery等类库来保证。
seajs.use(['jquery', './main'], function($, main) {
$(document).ready(function() {
main.init();
});
});
define
define是一个全局函数,用于定义模块。Sea.js推崇一个模块一个文件,遵循统一的写法。
- define(factory)
factory可以是一个函数,也可以是一个对象或字符串。
factory 为对象、字符串时,表示模块的接口是该对象、字符串。表示模块的接口就是该对象、字符串。比如:factory({“foo”:“bar”})
factory为函数时,表示模块的构造方法。执行该方法时,可以得到模块向外提供的接口。factory方法执行时,默认会传入三个参数require(接受模块标识作为唯一参数,用来获取其他模块提供的接口)、exports(用来向外提供模块接口)、module(存储了与当前模块相关联的一些属性和方法的对象)。
define(id?,deps?factory)
define也可以接受两个以上参数。字符串id表示模块标识,数组deps是模块依赖。
define('hello',['jquery'],function(require,exports,module){
//获取模块a的接口
var a=require('./a');
//调用模块a的方法
a.doSomething();
//异步加载一个模块,在加载完成后执行回调
require.async('./b',function(b){
b.dosomething()
})
//对外提供foo属性
exports.foo='bar'
//除了给exports对象增加成员,还可以使用return直接向外提供接口
return {
foo:'bar'
}
})
注意:
(1)exports仅仅是module.exports的一个引用。在factory内部给exports重新赋值时,并不会改变module.exports的值。因此给exports赋值是无效的,不能用来更改模块接口。
(2)对module.exports的赋值需要同步执行,不能放在回调函数中。
SeaJs 模块的地址解析规则
(1)顶级标识:以文件或目录(可以包含:字母、-、_)开头的,如:“app/widget”
顶级标识始终相对base基础路径解析
(2)相对标识:以“./”“../”,如:“./OtherModule”
相对标识始终相对当前页面解析
(3)绝对路径:相对于当前页面解析
(4)require和require.async中的相对路径相对当前模块路径来解析。
(5)seajs.use中的相对路径始终相对当前页面来解析。
base 路径的解析规则
(第一层,本身的路径不依赖于任何设置)
1 不可使用顶级标识,因为顶级标识就是相对于base基础路径来解析的,因此base本身只能使用相对标识或根路径
2 base默认路径为seajs的目录
3 base路径设置为相对路径则相对于当前页面进行解析。
paths 中路径解析规则
(第一层,本身的路径不依赖于任何设置)
1 相对标识:在哪里被引用,相对的解析位置被引用的地方而定,遵循当地的规则
2 paths中的字段会被以变量的方式在被使用的地方替换,然后再解析。
alias中路径解析规则
(第2层,本身的路径可以依赖paths的设置)
1 alias的规则类似于paths,并且alias路径也可以使用paths中的变量
2 paths,alias中尽量使用顶级标识、根路径、绝对路径,不要使用相对标识,因为在不同深度的模块引用时会解析为不同的路径。
总结
1 paths 、alias的设置仅仅相当于一个变量,在哪里使用就在哪里替换为设定的值,并解析
2 尽可能的使用顶级标识
3 若不能使用顶级标识,如目录跨越较大,则尽量设置alias或paths通过一个非相对路径标识定位到一个目录,然后在标识下再定义ID