loader
基于浏览器的 js 代码管理加载器
API
module(modName, [, dependenceList], init(mod)[, modConfig])
描述
模块定义
参数描述
- modName - 模块名以
.
分隔,因为需要和路径映射,通常符合文件命名规则即可 - dependenceList - 依赖模块列表,指定模块名即可,支持指定
@
,可选
当模块被加载时,其依赖会作为模块的一部分被加载,
如果需要异步的加载其他模块,可以使用require(modList, cb())
此处默认 ns 跟当前模块所在 ns 相同 - init - 模块初始化函数,在引用模块(
require
)的时候被调用,以初始化模块
此时,模块及模块的全部依赖都加载完毕 - modConfig - 模块配置 {}
- autoinit: true/false - 当模块及所有依赖加载完成后,立即初始化,
而不等待被引用 - embed: [] - 嵌入资源文件,用法见下面的例子,
资源文件会在模块初始化之前,跟随模块一起被加载 - provide: [] - 提供额外的 modName ,接口尚不稳定
- autoinit: true/false - 当模块及所有依赖加载完成后,立即初始化,
用法
1
// file a/b.js
module("a.b", function (mod) {
mod.init = function () {
// do some thing
};
return {
foo: function () {
alert("i'm " + mod._NAME);
}
};
});
通常每个模块存放到独立的 js 文件中,像上面一样
模块的初始化函数接收参数 mod ,这就是 require("a.b") 返回的结果啦(通常是这样,有例外)
模块可以对外提供属性和方法,添加的方式有2种:
- 设置 mod.prop = abc
- 在 init 函数内返回 { prop: abc } 这样的属性、方法列表
模块内置了以下属性和方法:
_NAME
- 模块名embed()
- 获取模块嵌入资源,这里接受的资源名和模块配置相同_getCfg()
- 获取模块内部定义,慎用
2
// file a/c.js
module("a.c", ["a.b"] function (mod) {
var b = require("a.b");
return {
foo: function () {
alert("embed got " + mod.embed("embed/c.jst"));
// 这里可以得到 c.jst 的文件内容,配合模版引擎就可以用了
}
};
}, {embed: ["embed/c.jst"]);
// file a/embed/c.jst
<% ctx.a %>
"some"
'text'
mod.embed()
可以得到嵌入资源内容 没有参数返回全部资源对象,key 是文件名
如果传入一个文件名,返回对应的文件内容 如果传入多个文件名,返回 资源列表
embed 文件的查找规则是 获取当前模块的加载路径,去掉文件名,拼上资源文件名,获取
资源文件是通过 ajax 获取的,所以,通常用于同域名开发阶段(跨域也可以,需要服务器支持
详情见 tool/embed.ngx 文件)
模块文件可以通过 tool/embed.js 来编译,这样 embed 资源都会被内嵌到模块文件内
(依赖 nodejs 和 uglify-js)
require(modAname, [, modBname], onAllLoad(modA ..))
描述
模块加载
参数描述
- modAname - 需要加载的模块列表,可指定多个模块,每个模块支持指定独立的 ns
- onAllLoad - 模块加载完成后的回调函数
返回值
如果待加载的模块全部可用(已加载),这里返回 true 否则返回 false
require
会并行加载全部模块,
模块加载后,会继续加载各模块的依赖,
所有模块及其依赖加载完毕后,会加载所有模块的资源文件(embed)
资源文件加载完毕后,开始调用 onAllLoad,
如果函数有参数,会主动初始化 require
的各个模块,并传递给 onAllLoad
(这里依赖 onAllLoad.length,所以函数内部使用 arguments 也许不是你想要)
用法
1
// file t.html
require("a.c", function (c) {
c.foo();
require("a.b", function (b) {
b.foo();
}) || alert("loading a.b");
});
require(modAname, [, modBname])
描述
模块引用
没有回调函数的 require
是引用,有回调函数的是加载
参数描述
- modAname - 需要引用的模块列表,一般只指定1个,支持多个
返回值
返回模块,需要模块已加载,无论是显式加载或者被模块依赖进来
如果给定多个参数,返回 模块数组
如果待引用的模块未正确加载,则抛异常
用法
1
// file t.html
require("a.c", function () {
require("a.c").foo();
require("a.b", function () {
require("a.b").foo();
}) || alert("loading a.b");
});
require.config([ns, ]config)
描述
配置 ns
ns 一般作用于模块加载和指定模块依赖的时候,因为这些地方需要计算模块对应的加载地址
指定 ns 的方式是在模块名后加 @lib
,其中 @
是关键字,lib
是 ns 的名字
每个 ns 有自己独立的配置
loader 内部是根据每个 ns 的 path 设置来计算模块名到加载路径映射的
参数描述
- ns - 指定配置哪个 ns,不指定就配置默认的那个
- config - 具体的配置 {}
- path: "" - 形式如
/js/m/?.js
loader 得到需要加载的模块后,会解析模块名和 ns ,
得到对应 ns 下面的 path
同时对模块名做替换,把 . 替换为 / ,然后替换 path 内的 ? 符号
就得到了最终的加载路径 - pkg: { "pkgname": ["modA", "modB"] } -
计算模块加载路径的时候,会预先判断是否有某个 pkg 提供了此模块,
如果有,就直接使用 pkg 代替当前模块去计算加载路径了 :)
- path: "" - 形式如
用法
1
// file http://a.ux/lib/jquery.js
module("jquery", function () {
// jquery
});
// file http://a.ux/lib/jquery/tmpl.js
module("jquery.tmpl", ["jquery"], function () {
// jquery.tmpl
});
// js/main.js
module("main", ["jquery.tmpl@lib"], function (mod) {
var tmpl = require("jquery.tmpl").tmpl,
$ = require("jquery").jquery;
mod.init = function (sel) {
$(sel).html(tmpl(mod.embed("main.jst"), {}));
};
}, {embed: ["main.jst"]});
// app.html
require.config("lib", { path: "http://a.ux/?.js" });
require.config({ path: "js/?.js" });
require("main", "jquery@lib", function (main, $) {
main.init($(document.body));
});
require.at(ns)
描述
当需要从某个 ns 加载大量模块的时候,可以使用此函数,
免去给每个模块都添加 @ns
的麻烦
require("a@lib", "b@lib", cb)
等价于
require.at("lib")("a", "b", cb)
module._genDepsDot()
描述
获取当前页面所有已加载模块的依赖图(dot 格式)
不复杂的 dot 可以在线解析( http://ashitani.jp/gv/ )
或者自己安装 http://www.graphviz.org/ 使用