一、require模块
+function() { var path = location.protocol + "//" + location.host +"/Javasript框架设计/common/"; require.config({ alias: { "jquery": { src: path + "mass/demo/jquery-1.9.1.min.js", deps: [],//没有依赖可以不写 exports: "jQuery" //要从全局作用域抽取的数据 } } }); require("jquery", function($) { alert($) alert($("body").length); alert("回调调起成功"); alert($("body").length) //这里不用domReady了 }) }()
以上是源码
我喜欢以剖析源代码的方式去学一种技术,上面这段代码是标准的requireJs的语句,但是这是mass.js版本的requireJs,下面就来解读源代码:
var path = location.protocol + "//" + location.host +"/Javasript框架设计/common/"
这个path是网站的根路径,方便mass寻找Js和css的文件.
require.config({
alias: {
"jquery": {
src: path + "mass/demo/jquery-1.9.1.min.js",
deps: [],//没有依赖可以不写
exports: "jQuery" //要从全局作用域抽取的数据
}
}
});
这段代码主要是记载系统的文件别名机制,通过给想要加载的文件起一个别名,并且指定该文件的路径。下面来看mass是如何实现这个功能的:
(function() { var cur = getCurrentScript(true); if (!cur) {//处理window safari的Error没有stack的问题 cur = $.slice(document.scripts).pop().src; } var url = cur.replace(/[?#].*/, ""); kernel = $.config; kernel.plugin = {}; kernel.alias = {}; basepath = kernel.base = url.slice(0, url.lastIndexOf("/") + 1); var scripts = DOC.getElementsByTagName("script"); for (var i = 0, el; el = scripts[i++]; ) { if (el.src === cur) { kernel.nick = el.getAttribute("nick") || "$"; break; } } kernel.level = 9; })();
通过这个自执行函数,将$.config函数对象托管给kernel对象
require.config = kernel;
然后在将kernel对象托管给require.config对象,require.config其实就是$.config函数对象,也就是说你通过require.config传递的参数,实际都会传递给$.config函数,个人觉得这个设计蛮不错的,当我们以后有新的模块需要进行类似的配置时,也可以通过这种方式,增强了代码的复用性。
再来看$.config做了什么?
config: function(settings) { for (var p in settings) { if (!hasOwn.call(settings, p)) continue; var val = settings[p]; if (typeof kernel.plugin[p] === "function") { kernel.plugin[p](val); } else { kernel[p] = val; } } return this; }
require.config({
alias: {
"jquery": {
src: path + "mass/demo/jquery-1.9.1.min.js",
deps: [],//没有依赖可以不写
exports: "jQuery" //要从全局作用域抽取的数据
}
}
});
源码传递给config一个属性名为alias的对象集合,然后通过config遍历这个集合,过滤其中的属性(不是该对象的原生属性(也就是通过原型链添加的属性)),然后判断当前遍历到的属性是否是kernel对象的插件(这里用函数表示),如果是吊用该插件,然后通过当前的属性,拿到对应对象的值,将值作为参数传递给该插件。
这里的alias是kernel的一个插件,下面是他的源码:
kernel.plugin["alias"] = function(val) { var map = kernel.alias; for (var c in val) { if (hasOwn.call(val, c)) { var prevValue = map[c]; var currValue = val[c]; if (prevValue) { $.error("注意" + c + "出经重写过"); } map[c] = currValue; } } };
这个函数也就是上面所说的alias插件,该函数通过维护一个alias集合来保存所有需要加载的文件的别名和对应的js路径
1、首先拿到所有的alias(别名),这里注意:
var all = "mass,lang,class,flow,data,support,query,node,attr,css,event,ajax,fx";
all.replace($.rword, function(a) { $.config.alias["$" + a] = basepath + a + ".js";
});
mass事先把属于自身框架的所有js文件都放到了这个集合当中去了。
2、遍历传入的参数,做一些常规判断,如果命名相同,则进行重写操作,并进行提醒,不相同直接加入到alias集合中去
加下来看require方法了:
require("jquery", function($) { alert($) alert($("body").length); alert("回调调起成功"); alert($("body").length) //这里不用domReady了 })
上面的代码传递给reqiire方法一个"jquery"和一个回调函数参数,下面来分析require方法的源码:
window.require = $.require = function(list, factory, parent) { // 用于检测它的依赖是否都为2 var deps = {}, // 用于保存依赖模块的返回值 args = [], // 需要安装的模块数 dn = 0, // 已安装完的模块数 cn = 0, id = parent || "callback" + setTimeout("1"); parent = parent || basepath; String(list).replace($.rword, function(el) { var url = loadJSCSS(el, parent) if (url) { dn++; if (modules[url] && modules[url].state === 2) { cn++; } if (!deps[url]) { args.push(url); deps[url] = "司徒正美"; //去重 } } }); modules[id] = {//创建一个对象,记录模块的加载情况与其他信息 id: id, factory: factory, deps: deps, args: args, state: 1 }; if (dn === cn) { //如果需要安装的等于已安装好的 fireFactory(id, args, factory); //安装到框架中 } else { //放到检测列队中,等待checkDeps处理 loadings.unshift(id); } checkDeps(); };
1、require方法接收三个参数:
(1)、第一个list,如果通过config配置过别名和路径的话,那么这个list就是别名列表,如果不是的话,LoadJSCSS方法会做进一步的处理,下面会介绍LoadJSCSS方法。
(2)、都二个factory,这个参数是回调函数
(3)、第三个parent,可以通过这个参数指定basePath,basePath下面也会介绍
2、