Seajs是一个JS代码异步加载工具、模块管理工具、模块依赖管理工具。
Seajs的模块写法方式和 node.js 的写法一样
类型判断
function isType(type) {
return function(obj) {
return {}.toString.call(obj) == "[object " + type + "]"
}
}
var isObject = isType("Object")
var isString = isType("String")
var isArray = Array.isArray || isType("Array")
var isFunction = isType("Function")
事件管理
seajs.on = function(name, callback) { // 绑定事件
}
seajs.off = function(name, callback) { // 删除事件绑定
}
var emit = seajs.emit = function(name, data) { // 触发事件
}
js请求
function request(url, callback, charset) {
var node = doc.createElement("script")//创建<script>标签对象
if (charset) {
var cs = isFunction(charset) ? charset(url) : charset
if (cs) {
node.charset = cs//设置字符
}
}
addOnload(node, callback, url)//注册onreadystatechange或者onload事件,在加载完成文件后,就删除<script>标签对象
node.async = true//设置异步加载
node.src = url//设置URL地址
// For some cache cases in IE 6-8, the script executes IMMEDIATELY after
// the end of the insert execution, so use `currentlyAddingScript` to
// hold current node, for deriving url in `define` call
currentlyAddingScript = node// JS对象
// ref: #185 & http://dev.jquery.com/ticket/2709
baseElement ?
head.insertBefore(node, baseElement) :
head.appendChild(node)//把对象加入到head
currentlyAddingScript = null
}
function addOnload(node, callback, url) {
var supportOnload = "onload" in node
if (supportOnload) {//支持onload事件
node.onload = onload
node.onerror = function() {
emit("error", { uri: url, node: node })
onload()
}
}
else {
node.onreadystatechange = function() {//onreadystatechange事件
if (/loaded|complete/.test(node.readyState)) {
onload()
}
}
}
function onload() {
// Ensure only run once and handle memory leak in IE
node.onload = node.onerror = node.onreadystatechange = null
// Remove the script to reduce memory leak
if (!data.debug) {
head.removeChild(node)//删除标签
}
// Dereference the node
node = null
callback()//调用回调
}
}
seajs.request = request;
解析依赖
var REQUIRE_RE = /"(?:\\"|[^"])*"|'(?:\\'|[^'])*'|\/\*[\S\s]*?\*\/|\/(?:\\\/|[^\/\r\n])+\/(?=[^\/])|\/\/.*|\.\s*require|(?:^|[^$])\brequire\s*\(\s*(["'])(.+?)\1\s*\)/g
var SLASH_RE = /\\\\/g
function parseDependencies(code) {//分析依赖
var ret = []
code.replace(SLASH_RE, "")
.replace(REQUIRE_RE, function(m, m1, m2) {
if (m2) {
ret.push(m2)
}
})
return ret
}
模块的对象化管理
function Module(uri, deps) {
}
Module.prototype.resolve = function() { // 转换模块的中的依赖的地址
}
Module.prototype.load = function() { // 加载模块
}
Module.prototype.onload = function() { // 加载模块后的回调
}
Module.prototype.fetch = function(requestCache) { // 下载依赖的JS文件
}
Module.prototype.exec = function () {// 执行模块的工厂方法
function require(id) {
return Module.get(require.resolve(id)).exec()
}
require.resolve = function(id) {
return Module.resolve(id, uri)
}
require.async = function(ids, callback) {
Module.use(ids, callback, uri + "_async_" + cid())
return require
}
// 模块的工厂方法
var factory = mod.factory
// 执行模块的工厂方法
var exports = isFunction(factory) ?
factory(require, mod.exports = {}, mod) :
factory
if (exports === undefined) {
exports = mod.exports;
}
// 删除模块的的工厂方法
delete mod.factory;
mod.exports = exports;
return exports;
}
Module.resolve = function(id, refUri) { // 把模块ID转成标准的地址
}
Module.define = function (id, deps, factory) { // 定义模块
if (!isArray(deps) && isFunction(factory)) {
deps = parseDependencies(factory.toString())// 解析模块的依赖
}
}
Module.save = function(uri, meta) { // 保存元信息(依赖、工厂方法、URI、ID)到模块中
}
Module.get = function(uri, deps) { // 创建模块
return cachedMods[uri] || (cachedMods[uri] = new Module(uri, deps))
}
Module.use = function (ids, callback, uri) { // 执行入口
var mod = Module.get(uri, isArray(ids) ? ids : [ids]);
mod.callback = function() { // JS文件加载完成的回调
}
mod.load()// 加载js文件
}
seajs.use = function(ids, callback) {
Module.use(ids, callback, data.cwd + "_use_" + cid());
return seajs;
}
global.define = Module.define;