# 模块系统
# 定义模块
//定义模块
Layui.prototype.define = function (deps, factory) {
var that = this,
type = typeof deps === "function",
callback = function () {
var setApp = function (app, exports) {
layui[app] = exports;
config.status[app] = true;
};
typeof factory === "function" &&
factory(function (app, exports) {
setApp(app, exports);
config.callback[app] = function () {
factory(setApp);
};
});
return this;
};
type && ((factory = deps), (deps = []));
that.use(deps, callback, null, "define");
return that;
};
# 使用模块
//使用特定模块
Layui.prototype.use = function (apps, callback, exports, from) {
var that = this,
dir = (config.dir = config.dir ? config.dir : getPath),
head = doc.getElementsByTagName("head")[0];
apps = (function () {
if (typeof apps === "string") {
return [apps];
}
//当第一个参数为 function 时,则自动加载所有内置模块,且执行的回调即为该 function 参数;
else if (typeof apps === "function") {
callback = apps;
return ["all"];
}
return apps;
})();
//如果页面已经存在 jQuery 1.7+ 库且所定义的模块依赖 jQuery,则不加载内部 jquery 模块
if (win.jQuery && jQuery.fn.on) {
that.each(apps, function (index, item) {
if (item === "jquery") {
apps.splice(index, 1);
}
});
layui.jquery = layui.$ = jQuery;
}
var item = apps[0],
timeout = 0;
exports = exports || [];
//静态资源host
config.host = config.host || (dir.match(/\/\/([\s\S]+?)\//) || ["//" + location.host + "/"])[0];
//加载完毕
function onScriptLoad(e, url) {
var readyRegExp = navigator.platform === "PLaySTATION 3" ? /^complete$/ : /^(complete|loaded)$/;
if (e.type === "load" || readyRegExp.test((e.currentTarget || e.srcElement).readyState)) {
config.modules[item] = url;
head.removeChild(node);
(function poll() {
if (++timeout > (config.timeout * 1000) / 4) {
return error(item + " is not a valid module", "error");
}
config.status[item] ? onCallback() : setTimeout(poll, 4);
})();
}
}
//回调
function onCallback() {
exports.push(layui[item]);
apps.length > 1
? that.use(apps.slice(1), callback, exports, from)
: typeof callback === "function" &&
(function () {
//保证文档加载完毕再执行回调
if (layui.jquery && typeof layui.jquery === "function" && from !== "define") {
return layui.jquery(function () {
callback.apply(layui, exports);
});
}
callback.apply(layui, exports);
})();
}
//如果引入了聚合板,内置的模块则不必重复加载
if (apps.length === 0 || (layui["layui.all"] && modules[item])) {
return onCallback(), that;
}
//获取加载的模块 URL
//如果是内置模块,则按照 dir 参数拼接模块路径
//如果是扩展模块,则判断模块路径值是否为 {/} 开头,
//如果路径值是 {/} 开头,则模块路径即为后面紧跟的字符。
//否则,则按照 base 参数拼接模块路径
var url =
(modules[item] ? dir + "modules/" : /^\{\/\}/.test(that.modules[item]) ? "" : config.base || "") +
(that.modules[item] || item) +
".js";
url = url.replace(/^\{\/\}/, "");
//如果扩展模块(即:非内置模块)对象已经存在,则不必再加载
if (!config.modules[item] && layui[item]) {
config.modules[item] = url; //并记录起该扩展模块的 url
}
//首次加载模块
if (!config.modules[item]) {
var node = doc.createElement("script");
node.async = true;
node.charset = "utf-8";
node.src =
url +
(function () {
var version = config.version === true ? config.v || new Date().getTime() : config.version || "";
return version ? "?v=" + version : "";
})();
head.appendChild(node);
if (
node.attachEvent &&
!(node.attachEvent.toString && node.attachEvent.toString().indexOf("[native code") < 0) &&
!isOpera
) {
node.attachEvent("onreadystatechange", function (e) {
onScriptLoad(e, url);
});
} else {
node.addEventListener(
"load",
function (e) {
onScriptLoad(e, url);
},
false
);
}
config.modules[item] = url;
} else {
//缓存
(function poll() {
if (++timeout > (config.timeout * 1000) / 4) {
return error(item + " is not a valid module", "error");
}
typeof config.modules[item] === "string" && config.status[item] ? onCallback() : setTimeout(poll, 4);
})();
}
return that;
};
# 拓展模块
//拓展模块
Layui.prototype.extend = function(options){
var that = this;
//验证模块是否被占用
options = options || {};
for(var o in options){
if(that[o] || that.modules[o]){
error(o+ ' Module already exists', 'error');
} else {
that.modules[o] = options[o];
}
}
return that;
};