您的位置:首页 > 产品设计 > UI/UE

RequireJS源码解读(二)

2017-03-24 17:02 351 查看
(续上节)

上面讲了如何处理全局序列和context化全局序列

以及执行全局序列中的依赖项。

检查依赖项

//Mark all the dependencies as needing to be loaded.
context.nextTick(function() {
//Some defines could have been added since the
//require call, collect them.
intakeDefines();

requireMod = getModule(makeModuleMap(null, relMap));

//Store if map config should be applied to this require
//call for dependencies.
requireMod.skipMap = options.skipMap;

requireMod.init(deps, callback, errback, {
enabled: true
});

checkLoaded();
});


最后返回的是 return localRequire;

回到 context.require(deps, callback, errback);

4. 监听页面加载

传入的参数是load加载事件

脚本加载的回调,用于检查加载状态。

onScriptLoad: function(evt) {
//Using currentTarget instead of target for Firefox 2.0's sake. Not
//all old browsers will be supported, but this one was easy enough
//to support and still makes sense.
if (evt.type === 'load' ||
(readyRegExp.test((evt.currentTarget || evt.srcElement).readyState))) {
//Reset interactive script so a script node is not held onto for
//to long.
interactiveScript = null;

//Pull out the name of the module and the context.
var data = getScriptData(evt);
context.completeLoad(data.id);
}


var data = getScriptData(evt) 这个函数 构造完毕之后,将返回一个对象



此时data就是{ node:script对象,id : ‘main’ }

5.获取加载对象

开始加载

completeLoad: function(moduleName) {
var found, args, mod,
shim = getOwn(config.shim, moduleName) || {},
shExports = shim.exports;

takeGlobalQueue();

while (defQueue.length) {
args = defQueue.shift();
if (args[0] === null) {
args[0] = moduleName;
//If already found an anonymous module and bound it
//to this name, then this is some other anon module
//waiting for its completeLoad to fire.
if (found) {
break;
}
found = true;
} else if (args[0] === moduleName) {
//Found matching define call for this script!
found = true;
}

callGetModule(args);
}
context.defQueueMap = {};

//Do this after the cycle of callGetModule in case the result
//of those calls/init calls changes the registry.
mod = getOwn(registry, moduleName);




运行到这里,callGetModule()就是调用module了吧



function callGetModule(args) {
//Skip modules already defined.
if (!hasProp(defined, args[0])) {
getModule(makeModuleMap(args[0], null, true)).init(args[1], args[2]);
}
}


传入的args :args = [“main”, Array[0], undefined]

args[1]和args[2]到底是来干嘛的?

5.1 创造ModuleMap对象

首先makeModuleMap(args[0], null, true)).init(args[1], args[2]

从下图可以看到args[1]是当前加载项的父节点, args[2]->applyMap?:



转化为绝对路径

最后将main.js转化为url路径,可能在这里没什么用,但是在这种定义了baseURL或者重命名模块中,这个normolize显得非常有用的



最后得到的对象:



5.2 getModule



5.3 Module.init



5.4 checkLoaded()

checkLoaded()会调用onScriptLoad(),出现了新的./@r5.js 是a.js吗



然而不是a.js,第二次遍历加载出了a.js



又见到熟悉的@r5.js,这次它变成了Module



6 加载第一个script:a.js

req.load = function(context, moduleName, url) {
var config = (context && context.config) || {},
node;
if (isBrowser) {
//In the browser so use a script tag
node = req.createNode(config, moduleName, url);

node.setAttribute('data-requirecontext', context.contextName);
node.setAttribute('data-requiremodule', moduleName);


6.1 检测是否是浏览器

isBrowser = !!(typeof window !== 'undefined' && typeof navigator !== 'undefined' && window.document),


6.2 创建node

req.createNode = function(config, moduleName, url) {
var node = config.xhtml ?
document.createElementNS('http://www.w3.org/1999/xhtml', 'html:script') :
document.createElement('script');
node.type = config.scriptType || 'text/javascript';
node.charset = 'utf-8';
node.async = true;
return node;
};


传入的参数:

这个path是在main.js中定义的

require.config({
path: {
"a": "a",
"b": "b"
}
})


deps=[‘main’],应该main默认就为依赖项吧,因为之前在



createNode()就是构造一段script,而且指定了charset-set 和async(异步加载);



node.setAttribute('data-requirecontext', context.contextName);
node.setAttribute('data-requiremodule', moduleName);


这两句话为node添加了新的属性



为node绑定新的事件

node.addEventListener('load', context.onScriptLoad, false);
node.addEventListener('error', context.onScriptError, false);


加载事件和error事件都绑定为context的对象了

其实node就是script,但是require这里为它添加了两个新的属性和新的load处理事件,我觉得requireJS的精妙之处就在这里吧。

继续循环看是否有加载项

这个时候a.js并没有加载,又出现了.@r5,我猜测b.js要出来了



然而我们看到的是,removeScript(“a”),要移除a了?但是a都没有加载啊



不对,这里是要加载a.js,然而报错了,应该是因为我们debug超出了requireJS的时间。



.@r6 .@r8出现了

先写到这里,requireJS的原理确切是很复杂,经常会对一些全局变量进行修改啥的。

到这里onScriptLoad()就结束了
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: