javascript动态加载三


Posted in Javascript onAugust 22, 2012

之前两篇都介绍了,通过动态加载JS文件或者说JS模块,是怎么一步一步实现。

首先是通过同步策略来实现模块加载与回调函数之间进行分离,接着是通过异步策略来实现模块加载与回调函数之间进行分离。

这一篇,主要是为了说说怎么优化异步策略,并且实现了随意加载(非任意顺序加载模块),页面Ready之后加载文件。先接一下上一篇遗留下来的问题

1、页面Ready之后进行加载

2、随意添加模块 进行加载

看第一个问题,这个问题其实还是比较简单的,主要是监听页面的DOMContentLoaded事件,这里就不多讲解,网络上搜索,一堆答案,直接上代码。

Using.ready = function(callback){ 
readyList.push(callback); if(document.addEventListener){ 
document.addEventListener("DOMContentLoaded",_ready,false); 
return; 
} 
// for IE 
var domReady = function(){ 
try{ 
document.documentElement.doScroll("left"); 
_ready(); 
}catch(ex){ 
setTimeout(domReady,1); 
return; 
} 
} 
domReady(); 
}

这一段代码中最难以理解的应该就是
document.documentElement.doScroll("left");

这里其实是IE的页面加载完毕事件,简单说就是IE里面标签加载完毕之后,是可以操作Scroll的,那就根据此原理来判断IE中页面是否加载完毕。

里面有一个_ready函数,这个函数就是用来做页面加载完毕之后执行所有加载的函数。贴一下代码

(编辑一下这一段:页面加载完毕Ready函数并不是我们思想中所认为的原生JS的window.load,简单说只是页面中DOM结构的加载完毕,具体信息,可自行百度google之)

var readyList = []; 
var _ready = function(){ 
while(readyList.length > 0){ 
var func = readyList.shift(); 
func(); 
} 
document.removeEventListener("DOMContentLoaded",_ready,false); 
}

下面就是本博文的重点了。还是先看一下代码
Using.asyn = function(callback){ 
asynQueue.push(callback); 
if(!_execAsyn.isRunning){ 
_execAsyn(); 
} 
}

还是通知Using要加载所需要的模块了,只不过里面加入了一个asynQueue数组和_execAsyn函数,他们的作用分别是

asynQueue是用来保存异步加载之后要回调的函数,没什么好解释的,是一个数组,可以理解为创建了一个函数的队列

_execAsyn是用来执行保存的那些回调函数的,即将所保存的函数逐一执行。看一下代码,代码中对每行的作用都进行了注释

var _execAsyn = function(){ 
// 创建一个变量来缓存需要执行的函数 
var func = null; 
// 如果队列中还有未执行的函数 则进行执行操作 
if(asynQueue.length > 0){ 
// 将_execAsyn函数修改为运行状态 
_execAsyn.isRunning = true; 
// 得到队列中第一个需要执行的函数 
func = asynQueue.shift(); 
// 调用异步加载模块Using.fn.script函数 并传入加载完毕之后需要执行的回调函数 
Using.fn.script(function(){ 
// 当前需要执行的函数 
func(); 
// 迭代_execAsyn 直到队列中没有需要执行的函数 
_execAsyn(); 
}); 
// 若队列中没有需要执行的函数 
}else{ 
// 则将_execAsyn运行状态改为false 
_execAsyn.isRunning = false; 
} 
}

这个函数,解释起来没什么特别的,说白了就是一个一个的执行需要执行的函数。那么,唯一需要注意的就是为什么操作队列的时候没有采用循环,而是使用迭代。那原因就是

1、队列中随时可能有新的函数需要执行,采用循环的话,可能执行不到最新的函数,因为函数总是插入到队列的尾部

2、 Using.fn.script是异步的,如果是循环的话,当前函数还没有执行完,可能下一个函数就已经进入了执行状态。那么,本身来说,同时执行几个函数,速率上可能会更高,为什么这里还要限制其多个函数并行呢?原因也很简单,因为每一次执行队列中的函数,可能都需要加载相应的模块,那么如果刚好友两个或者多个依赖相同模块的函数需要执行,而且并行执行,就可能出现同一个模块加载多次,并可能造成后续的函数执行不了,出现异常。

整个UsingJS的核心部分就这些。在其中我加入了Using.Class.create函数,这个函数在javascript动态加载文章的末尾有提到。

最后看一下页面使用情况:

<script type="text/javascript" src="js/using-0.4.2.min.js"></script> 
<script type="text/javascript"> 
Using("jq"); 
Using("UserView"); 
Using("jq"); Using.ready(function(){ 
Using.asyn(function(){ 
$("#panel").click(function(){ 
alert("by jquery"); 
}); 
}); 
}); 
Using.ready(function(){ 
Using("Http"); 
Using.asyn(function(){ 
var http = new Using.Modules.Http(); 
http.set("xxx"); 
http.show(); 
}); 
Using.asyn(function(){ 
var h = new Using.Modules.Http(); 
h.set("ooo"); 
h.show(); 
}); 
Using("jq"); 
Using.asyn(function(){ 
$("#panel").click(function(){ 
alert("loaded jquery"); 
}); 
}); 
}); 
</script>

这个一段代码,刻意进行重复加载,多次Ready事件和Ready之后进行Using导包。

有一个特别需要注意的地方

Using("Http"); 
Using.asyn(function(){ 
var http = new Using.Modules.Http(); 
http.set("xxx"); 
http.show(); 
}); 
// 假如在这个地方使用 
// var ht = new Using.Modules.Http(); 
// 是会报Using.Modules.Http不是一个constructor 
// 原因就是 
// 任何操作都是异步的,当执行此句时Using("Http")这个模块载入可能还没有完成 
// 这一点是仲谋给多个朋友进行使用时会犯的错误 总以为导包之后 万事大吉 
// 是的 本身应该是这样 导包之后 在任何地方都可以随意引用 
// 但是总得有个前提吧 那就是模块得加载完毕 
// 所以 还请将所有的代码都写在Using.asyn之内 
Using.asyn(function(){ 
var h = new Using.Modules.Http(); 
h.set("ooo"); 
h.show(); 
});

UsingJS下载
Javascript 相关文章推荐
js innerHTML 的一些问题的解决方法
Jun 22 Javascript
javascript 函数调用的对象和方法
Jul 01 Javascript
如何阻止复制剪切和粘贴事件为了表单内容的安全
May 23 Javascript
IE8下Jquery获取select选中的值post到后台报错问题
Jul 02 Javascript
给js文件传参数(详解)
Jul 13 Javascript
javascript获取当前鼠标坐标的方法
Jan 10 Javascript
JavaScript中的setMilliseconds()方法使用详解
Jun 11 Javascript
高效的jquery数字滚动特效
Dec 17 Javascript
jQuery双向列表选择器select版
Nov 01 Javascript
JS验证字符串功能
Feb 22 Javascript
详解vue项目优化之按需加载组件-使用webpack require.ensure
Jun 13 Javascript
vue项目创建步骤及路由router
Jan 14 Javascript
javascript动态加载二
Aug 22 #Javascript
javascript动态加载实现方法一
Aug 22 #Javascript
原生js写的放大镜效果
Aug 22 #Javascript
window.open不被拦截的实现代码
Aug 22 #Javascript
EASYUI TREEGRID异步加载数据实现方法
Aug 22 #Javascript
网页打开自动最大化的js代码
Aug 22 #Javascript
精心挑选的12款优秀的基于jQuery的手风琴效果插件和教程
Aug 22 #Javascript
You might like
php常用表单验证类用法实例
2015/06/18 PHP
PHP无限极分类函数的实现方法详解
2017/04/15 PHP
php源码的安装方法和实例
2019/09/26 PHP
js 赋值包含单引号双引号问题的解决方法
2014/02/26 Javascript
css+js实现部分区域高亮可编辑遮罩层
2014/03/04 Javascript
快速掌握Node.js模块封装及使用
2016/03/21 Javascript
AngularJS入门教程之控制器详解
2016/07/27 Javascript
nodejs入门教程四:URL相关模块用法分析
2017/04/24 NodeJs
详解react-router4 异步加载路由两种方法
2017/09/12 Javascript
一个简易时钟效果js实现代码
2020/03/25 Javascript
Vue调试神器vue-devtools安装方法
2017/12/12 Javascript
NodeJS 文件夹拷贝以及删除功能
2019/09/03 NodeJs
修改vue源码实现动态路由缓存的方法
2020/01/21 Javascript
在DigitalOcean的服务器上部署flaskblog应用
2015/12/19 Python
Python 使用requests模块发送GET和POST请求的实现代码
2016/09/21 Python
python版微信跳一跳游戏辅助
2018/01/11 Python
python爬取网页转换为PDF文件
2018/06/07 Python
将string类型的数据类型转换为spark rdd时报错的解决方法
2019/02/18 Python
对PyQt5中树结构的实现方法详解
2019/06/17 Python
Python模块汇总(常用第三方库)
2019/10/07 Python
Python箱型图处理离群点的例子
2019/12/09 Python
python圣诞树编写实例详解
2020/02/13 Python
flask开启多线程的具体方法
2020/08/02 Python
CSS3的文字阴影—text-shadow的使用方法
2012/12/25 HTML / CSS
canvas实现滑动验证的实现示例
2020/08/11 HTML / CSS
The North Face北面英国官网:美国著名户外品牌
2017/12/13 全球购物
心理健康心得体会
2014/01/02 职场文书
培训专员岗位职责
2014/02/26 职场文书
公司授权委托书范本
2014/04/03 职场文书
车间安全生产标语
2014/06/06 职场文书
艺术设计专业毕业生推荐信
2014/07/08 职场文书
2014入党积极分子破除“四风”思想汇报
2014/09/14 职场文书
工作收入住址证明
2014/10/28 职场文书
2014年宣传工作总结
2014/11/18 职场文书
邀请书模板
2015/02/02 职场文书
结婚喜宴迎宾词
2015/08/10 职场文书