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";
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下面也会介绍
- 数据迁移判断非空约束(r2笔记45天)
- 【专业技术】linux下socket编程
- oracle并行的小细节(r2笔记44天)
- python实现朴素贝叶斯模型:文本分类+垃圾邮件分类
- 使用闪回查询备份数据(r2笔记43天)
- 生产环境sql语句调优实战第四篇(r2笔记41天)
- 生产环境sql语句调优实战第五篇(r2笔记41天)
- python实现逻辑logistic回归:预测病马的死亡率
- 开发 | 图片数据集太少?看我七十二变,Keras Image Data Augmentation 各参数详解
- linux过滤空文件的命令总结(r2笔记40天)
- shell脚本自动化采集性能sql(r2笔记39天)
- R语言与点估计学习笔记(EM算法与Bootstrap法)
- 开发 | 为个人深度学习机器选择合适的配置
- 阿里音乐流行趋势预测竞赛数据清洗整合——纯python
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- laravel利用中间件做防非法登录和权限控制示例
- laravel框架中表单请求类型和CSRF防护实例分析
- Yii框架getter与setter方法功能与用法分析
- laravel框架中视图的基本使用方法分析
- laravel5 Eloquent 实现事务方式
- Laravel 微信小程序后端搭建步骤详解
- Laravel使用swoole实现websocket主动消息推送的方法介绍
- Laravel框架Eloquent ORM删除数据操作示例
- PHP常用函数之base64图片上传功能详解
- laravel-admin 实现在指定的相册下添加照片
- Laravel框架Eloquent ORM修改数据操作示例
- PHP常用函数之格式化时间操作示例
- 在phpstudy集成环境下的nginx服务器下配置url重写
- 关于laravel-admin ueditor 集成并解决刷新的问题
- PHP常用函数之根据生日计算年龄功能示例