最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
当前位置: 首页 - 科技 - 知识百科 - 正文

用js实现简易模块加载器的方法

来源:动视网 责编:小采 时间:2020-11-27 20:12:11
文档

用js实现简易模块加载器的方法

用js实现简易模块加载器的方法:前言前一段时间分析过require.js源码,整体的分析有些泛泛而,谈内容有些空洞,没有把握住requirejs依赖处理的精髓, 这是分析require.js源码最为失败的地方。虽然没有真正的理解其实现细节,但是对其源码组织以及基本的逻辑执行有了整体的了解。本文是参考网
推荐度:
导读用js实现简易模块加载器的方法:前言前一段时间分析过require.js源码,整体的分析有些泛泛而,谈内容有些空洞,没有把握住requirejs依赖处理的精髓, 这是分析require.js源码最为失败的地方。虽然没有真正的理解其实现细节,但是对其源码组织以及基本的逻辑执行有了整体的了解。本文是参考网


Module的原型对象有如下几个方法:

init:Module对象的初始化处理
fetch:创建script节点并追加到元素节点上
checkCycle:处理循环依赖,返回当前的循环依赖列表
handleDeps:处理依赖列表
changeStatus:改变模块的状态,主要处理模块是否加载成功
execute:依赖的模块都加载成功后,参数列表的获取

如何处理依赖列表的

事实上,处理依赖列表是define以及require中处理,define函数以及require函数的处理代码如下:

首先看require函数,实例:

require(['a', 'b'], function(a, b) {
 console.log(a, b);
});

从上面可以看出,调用require函数,依赖列表是[‘a’, ‘b’],回调函数是function(a, b) {console.log(a, b);}

从require代码可以就看出,调用Context构造函数创建一个Context对象,现在看下Context构造函数的处理:let Context = function(deps, callback, errback) {

 this.cid = ++contextId;
 this.init(deps, callback, errback);
}
;
 Context.prototype.init = function(deps, callback, errback) {
 this.deps = deps;
 this.callback = callback;
 this.errback = errback;
 contexts[this.cid] = this;
}
;

上面中重要的是contexts[this.cid] = this;将当前的Context对象注册到全局contexts对象集合中。

然后调用handleDeps函数,该函数处理依赖列表,具体的代码如下:handleDeps: function() {

 let depCount = this.deps ? this.deps.length : 0;
 // require.js中处理循环依赖的处理 let requireInDep = (this.deps || []).indexOf('require');
 if (requireInDep !== -1) {
 depCount--;
 this.requireInDep = requireInDep;
 this.deps.splice(requireInDep, 1);
}
// 处理循环依赖情况 let cycleArray = this.checkCycle();
 if (cycleArray) {
 depCount = depCount - cycleArray.length;
}
// depCount表示当前模块的依赖模块数,depCount为0表示模块中某一依赖加载完成 this.depCount = depCount;
 if (depCount === 0) {
 this.execute();
 return;
}
// 遍历依赖列表,创建Module对象,并且将当前模块与其依赖的关系构建出来maps this.deps.forEach((depModuleName) => {
 if (!modules[depModuleName]) {
 let module = new Module(depModuleName);
 modules[module.name] = module;
}
if (!maps[depModuleName]) {
 maps[depModuleName] = [];
}
maps[depModuleName].push(this);
}
);

}循环依赖的处理

本次实现代码中的循环依赖的处理,是require.js中官方的方法,就是传递require在回调函数中再次require,为什么这样就可以解决循环依赖?

就本次实现而言,因为require一次就会创建一个Context对象。主要代码如下:// require.js中处理循环依赖的处理let requireInDep = (this.deps || []).indexOf('require');

 if (requireInDep !== -1) {
 depCount--;
 this.requireInDep = requireInDep;
 this.deps.splice(requireInDep, 1);
}
// 获取循环依赖 let cycleArray = this.checkCycle();
 if (cycleArray) {
 depCount = depCount - cycleArray.length;
}
// execute函数中代码// 插入require到回调函数的参数列表中if (this.requireInDep !== -1 && this.requireInDep !== undefined) {
 arg.splice(this.requireInDep, 0, require);
}

结束语

纸上得来终觉浅,觉知此事要躬行,通过实现简易的模块加载器,对于require.js模块加载的思想以及逻辑处理更加地清晰。

虽然与require.js对于js文件的异步加载的处理方式不同,但是本质是一样的,require.js是添加script节点到head标签中,并且script添加async属性来实现异步加载的。

文档

用js实现简易模块加载器的方法

用js实现简易模块加载器的方法:前言前一段时间分析过require.js源码,整体的分析有些泛泛而,谈内容有些空洞,没有把握住requirejs依赖处理的精髓, 这是分析require.js源码最为失败的地方。虽然没有真正的理解其实现细节,但是对其源码组织以及基本的逻辑执行有了整体的了解。本文是参考网
推荐度:
标签: 方法 实现 js
  • 热门焦点

最新推荐

猜你喜欢

热门推荐

专题
Top