JS模块加载系统设计V1
一、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、
JS模块加载系统设计V1的更多相关文章
- nodejs js模块加载
本文地址:http://www.cnblogs.com/jasonxuli/p/4381747.html nodejs的非核心模块(core module)加载主要使用的就是module.js. 项目 ...
- js模块化/js模块加载器/js模块打包器
之前对这几个概念一直记得很模糊,也无法用自己的语言表达出来,今天看了大神的文章,尝试根据自己的理解总结一下,算是一篇读后感. 大神的文章:http://www.css88.com/archives/7 ...
- js模块加载之AMD和CMD
当我写这篇文章的时候,sea.js已经逐渐退出历史的舞台,详细链接.不过任何新事物的出现都是对旧事物的取其精华,去其糟粕,所以了解一下以前模块的加载也是一件好事. js模块化的原因自不比多说,看看HU ...
- sea.js模块加载工具
seajs的使用 seajs是一个jS模块加载器,由淘宝前端架构师玉伯开发,它可以解决命名空间污染,文件依赖的问题.可以在一个js文件中引入另外一个js.require('a.js') 1.安装 np ...
- 实现简单的 JS 模块加载器
实现简单的 JS 模块加载器 1. 背景介绍 按需加载是前端性能优化的一个重要手段,按需加载的本质是从远程服务器加载一段JS代码(这里主要讨论JS,CSS或者其他资源大同小异),该JS代码就是一个模块 ...
- 第三课:sea.js模块加载原理
模块加载,其实就是把js分成很多个模块,便于开发和维护.因此加载很多js模块的时候,需要动态的加载,以便提高用户体验. 在介绍模块加载库之前,先介绍一个方法. 动态加载js方法: function l ...
- JS模块加载器加载原理是怎么样的?
路人一: 原理一:id即路径 原则.通常我们的入口是这样的: require( [ 'a', 'b' ], callback ) .这里的 'a'.'b' 都是 ModuleId.通过 id 和路径的 ...
- Node.js模块 加载笔记
//核心模块就是Node.js标准API种提供的模块,如fs,http,net.vm等.官方提供,编译成二进制代码//核心模块拥有最高的加载优先级 //文件模块则是存储为单独的文件(或文件夹)的模块, ...
- 关于前端JS模块加载器实现的一些细节
最近工作需要,实现一个特定环境的模块加载方案,实现过程中有一些技术细节不解,便参考 了一些项目的api设计约定与实现,记录下来备忘. 本文不探讨为什么实现模块化,以及模块化相关的规范,直接考虑一些技术 ...
随机推荐
- [Windows] IIS7.5 部署ISAPI
环境: OS:Windows Server 2008 R2 Enterprise sp1 64位 IIS:7.5 ISAPI: delphi xe 编译的webbroker isapi dll 3 ...
- MIDA Converter Basic patched for RAD Studio 10.1.2 Berlin (VCL转换到FMX)
Mida is the only way to try to convert your project from VCL to FireMonkey. Version after version, M ...
- [示例] Firemonkey 画出 1 点像素的线
说明:在 Firemonkey 在移动平台 Android & iOS 要直接在 Canvas 画出 1 点像素的线,似乎有点困难,不过利用一点小技巧,还是能达到这个要求的,首先要建立一个 B ...
- Replication--Alwayson+复制发布
场景:主服务器:RepServer1从服务器:RepServer2监听者:RepListener分发库:DisServer发布数据库:RepDB1配置:1>设置DisServer为分发服务器,在 ...
- php获取数组的键值
<?php header ( "Content-type: text/html; charset=utf-8" ); $info[; $info[; $info[; $inf ...
- SQL命令行修改数据库
增加列: alter table tableName add columnName varchar(30) 修改列类型:alter table tableName alter column colum ...
- docker 进入容器
- Webbench的使用
Webbench是一个在linux下使用的非常简单的网站压测工具. 它使用fork()模拟多个客户端同时访问我们设定的URL,测试网站在压力下工作的性能,最多可以模拟3万个并发连接去测试网站的负载能力 ...
- IdentityServer4与ocelot实现认证与客户端统一入口
关于IdentityServer4与ocelot博客园里已经有很多介绍我这里就不再重复了. ocelot与IdentityServer4组合认证博客园里也有很多,但大多使用ocelot内置的认证,而且 ...
- MySQL数据库(四)
操作数据库表的内容: -- 向表中插入数据:insert into table_name values(now(),'a'); insert into student (id,name,sex) va ...