javascript不依赖JS加载顺序事件对象实现

背景:

  在现在WEB开发中,稍复杂一点的页面,都会涉及到多个模块,尤其是类似seajs、LABjs、requireJS等模块工具出来后,前端开发者分模块开发已经慢慢变成一种习惯了,但是多个模块间的常常有各种交集,需要通信、需要互相调用,这时监听者模式便是必不可少的一种设计模式了,在前端表现事件操作。backbone和jquery都有提供了很好的事件处理方式。

  但是,真正开发需求的时候我们常常会遇到文件加载顺序跟事件监听与更新不一致的需求,比如说:在一个视频网站里面,有一个视频处理的JS模块和用户信息处理模块,现在需要先加载视频模块的JS使得能第一时间把视频展示给用户看,但是在展示完视频的同时需要视频JS模块会更新一个在用户信息处理模块里面监听的发送用户查看视频记录的模块,这时候由于用户信息处理模块未加载,所以会导致事件未定义且不被执行,这时我们希望的是就算是之前更新的,用户信息处理模块在初始化监听时能知道之前已经被更新过了,并执行该更新。下面就是来实现不依赖JS加载顺序事件对象的实现吧:

基础:


(function(){
var obListenList = {}; //监听者事件列表
var OB = {
listen : function(listenStr,func){
if(!obListenList[listenStr]){
obListenList[listenStr] = [];
}
obListenList[listenStr].push(func);
},
update : function(listenStr,datas){
if(typeof obListenList[listenStr] != "undefined"){
var len = obListenList[listenStr].length,
i = 0;
for( ; i < len ; i++){
if(typeof(obListenList[listenStr][i])=="function"){
obListenList[listenStr][i](datas);
}
}
}
}
};
window.OB = OB;
}());

OB.listen("say",function(msg){
document.write(msg + "<br/>");
});
OB.update("say","She say : Im your‘s!");

  基础的事件编写很简单,只需要用一个对象把被监听的事件的函数列表放在一个对象(obListenList)里面,在update的时候查看遍历调用就是了。

实现先更新,等监听的时候也会执行之前的更新:


(function(){
var obListenList = {}, //监听事件列表
obUpdateList = {} , // 更新事件列表
obUpdateListLen = 2 , //最大监听更新队列数
obUpdateWaitFlag = true ;

var OB = {
listen : function(listenStr,func){
if(!obListenList[listenStr]){
obListenList[listenStr] = [];
}
obListenList[listenStr].push(func);

//查看之前是否有更新过
if(typeof obUpdateList[listenStr] != "undefined"){
var lStrArg = obUpdateList[listenStr];
for(var i = 0 ; i < lStrArg.length; i ++ ){
func(lStrArg[i]);
}
}

},
update : function(listenStr,datas){

if(typeof obListenList[listenStr] != "undefined"){
var len = obListenList[listenStr].length,
i = 0;
for( ; i < len ; i++){
if(typeof(obListenList[listenStr][i])=="function"){
obListenList[listenStr][i](datas);
}
}
}
if(obUpdateWaitFlag){

//往该事件更新队列里面添加数据
if(typeof obUpdateList[listenStr] == "undefined"){
obUpdateList[listenStr] = [];
}
obUpdateList[listenStr].push(datas);

//如果超过允许的最大长度就不要再往里面添加了,防止内在溢出
if(obUpdateList[listenStr].length>=obUpdateListLen){
obUpdateWaitFlag = false;
}
}
}
};
window.OB = OB;
}());

OB.update("say","She say : Im your‘s!--1");
OB.update("say","She say : Im your‘s!--2");
OB.update("say","She say : Im your‘s!--3");
OB.listen("say",function(msg){
document.write(msg + "<br/>");
});
OB.update("say","She say : Im your‘s!--4");

/* 结果是:
* She say : Im your‘s!--1
* She say : Im your‘s!--2
* She say : Im your‘s!--4
*/

  看下代码,实现起来也不是很难有三个关键点:

    1,在更新事件的时候将事件传入的参数传进更新事件列表里面

    2,在监听事件初始化后,查看更新事件列表里面有没有对应事件需要更新的数据,如果有,便遍历执行一遍

    3,一定要给更新事件列表设定一个最大保留监听的事件长度(obUpdateListLen),因为在一些复杂的页面程序中可能会有某个无限的更新,如果不做限制必然导致内存溢出。

优化:


(function() {

if(typeof OB !== "undefined"){//防止文件重复加载导致事件队列被清空
return ;
}

var obListenList = {} , //存储监听队列
obUpdateList = {} , //存储更新队列
obUpdateListLen = 2 , //存储更新队列最多保存长度
obUpdateWaitFlag = true ; //记录是否达到了存储更新队列的最大值

var OB = function (listenStr){
return new OB.prototype.init(listenStr);
};

OB.prototype = {
listenStr : "",
instance : null,
init : function(listenStr){
if(OB.prototype.instance){
OB.prototype.instance.setListenStr(listenStr);
return OB.prototype.instance;
}

this.setListenStr(listenStr);

OB.prototype.instance = this;
return this;
},
setListenStr : function(listenStr){
this.listenStr = listenStr;
},
listen : function(func){
if(this.listenStr){
if(!obListenList[this.listenStr]){
obListenList[this.listenStr] = [];
}
obListenList[this.listenStr].push(func);

//查看之前是否有更新过
if(typeof obUpdateList[this.listenStr] != "undefined"){
var lStrArg = obUpdateList[this.listenStr];
for(var i = 0 ; i < lStrArg.length; i ++ ){
func.apply(this,lStrArg[i]);
}
}
}
},
update : function(){
if(typeof obListenList[this.listenStr] != "undefined"){
var len = obListenList[this.listenStr].length,
i = 0;
for( ; i < len ; i++){
if(typeof(obListenList[this.listenStr][i])=="function"){
obListenList[this.listenStr][i].apply(this,arguments);
}
}
}
if(obUpdateWaitFlag){
if(typeof obUpdateList[this.listenStr] == "undefined"){
obUpdateList[this.listenStr] = [];
}
obUpdateList[this.listenStr].push(arguments);

if(obUpdateList[this.listenStr].length>=obUpdateListLen){
obUpdateWaitFlag = false;
}
}
}
};

OB.prototype.init.prototype = OB.prototype;
window.OB = OB;

//兼容seaJS和requireJS
if ( typeof define === "function" && ( define.cmd || define.amd ) ) {
define( "jquery", [], function() {
return OB;
});
}

}());

OB("say").update("She say : Im your‘s!--1");
OB("say").update("She say : Im your‘s!--2");
OB("say").update("She say : Im your‘s!--3");
OB("say").listen(function(msg){
document.write(msg + "<br/>");
});
OB("say").update("He Say : yes! you are mine!");

/* 结果是:
* She say : Im your‘s!--1
* She say : Im your‘s!--2
* He Say : yes! you are mine!
*/

  这里主要是几个点的优化:

  1,操作优化,使用了JQuery原型模式实现了JQuery操作方式,具体的原理可以参考《犀利开发:jQuery内核详解与实践》 这本书

  2,支持AMD和CMD模块,方便直接应用到SeaJS或requireJS等项目

  3,防止重复加载导致事件列表被清空

这个只是本人的实践经历,写法可能没有那么优美,但是基本功能已经出来了,希望对大家的项目有所帮助,如果有存在什么问题,也可以回复一下。

javascript不依赖JS加载顺序事件对象实现,布布扣,bubuko.com

时间: 2024-10-26 04:58:53

javascript不依赖JS加载顺序事件对象实现的相关文章

(转)JS加载顺序

原文:http://blog.csdn.net/dannywj1371/article/details/7048076 JS加载顺序 做一名合格的前端开发工程师(12篇)--第一篇 Javascript加载执行问题探索 楼主做前端开发一年多了,对前端的见解还是多多少少有一点的,今天特拿出来跟大家分享分享. 做前端开发少不了各种利器.比如我习惯用的还是Google浏览器和重型武器Fiddller. 一: 原始情况 首先大家看看如下的代码: 1 <%@ Page Language="C#&qu

thinksns系统的js加载顺序整理

thinksns系统的js加载顺序整理 1.jQuery.js 2.jquery.form.js 3.common.js 4.core.js   //thinksns的核心js对象 5.module.js   //thinksns独有的HTML标签关联模型 6.module.common.js ................................................希望资深的前端大牛能给讲解一下内部的工作原理

html css js加载顺序

1.js放在head中会立即执行,阻塞后续的资源下载与执行.因为js有可能会修改dom,如果不阻塞后续的资源下载,dom的操作顺序不可控. 正常的网页加载流程是这样的. 浏览器一边下载HTML网页,一边开始解析 解析过程中,发现<script>标签 暂停解析,网页渲染的控制权转交给JavaScript引擎 如果<script>标签引用了外部脚本,就下载该脚本,否则就直接执行 执行完毕,控制权交还渲染引擎,恢复往下解析HTML网页 如果外部脚本加载时间很长(比如一直无法完成下载),就

js加载顺序

一两个月前在淘宝内网里看到一个优化Javascript代码的竞赛,发现有不少的人对Javascript的执行和装载的基础并不懂,所以,从那天起我就想写一篇文章,但一直耽搁了.自上篇<浏览器渲染原理简介>,正好也可以承前启后. 首先,我想说一下Javascript的装载和执行.通常来说,浏览器对于Javascript的运行有两大特性:1)载入后马上执行,2)执行时会阻塞页面后续的内容(包括页面的渲染.其它资源的下载).于是,如果有多个js文件被引入,那么对于浏览器来说,这些js文件被被串行地载入

css/js 加载顺序

Firefox and Opera are the only browsers capable of loading  scripts in parallel while preserving execution order. In all other browsers, scripts must be loaded sequentially. //只有Firefox和opera支持并行加载脚本,并保持执行顺序.其他游览器必须按顺序进行加载. All browsers respect CSS s

JS 页面加载触发事件 document.ready和window.onload的区别

document.ready和onload的区别——JavaScript文档加载完成事件页面加载完成有两种事件: 一是ready,表示文档结构已经加载完成(不包含图片等非文字媒体文件): 二是onload,指示页面包含图片等文件在内的所有元素都加载完成. 1.Dom Ready 使用jq时一般都是这么开始写脚本的: $(function(){ // do something }); 例如: $(function() { $("a").click(function() { alert(&

JS 页面加载触发事件 document.ready和onload的区别

JS 页面加载触发事件 document.ready和onload的区别 document.ready和onload的区别——JavaScript文档加载完成事件 页面加载完成有两种事件: 一是ready,表示文档结构已经加载完成(不包含图片等非文字媒体文件): 二是onload,指示页面包含图片等文件在内的所有元素都加载完成. 1.Dom Ready 用jQ的人很多人都是这么开始写脚本的: $(function(){       // do something }); 例如: $(functi

javascript在html中的加载顺序

参考:[1]http://coolshell.cn/articles/9749.html(酷壳) [2]http://shaozhuqing.com/?p=2756 颜色标注分别来自于链接地址内容 通常来说,浏览器对于Javascript的运行有两大特性:1)载入后马上执行,2)执行时会阻塞页面后续的内容(包括页面的渲染.其它资源的下载).于是,如果有多个js文件被引入,那么对于浏览器来说,这些js文件被被串行地载入,并依次执行. 因为javascript可能会来操作HTML文档的DOM树,所以

原生JS实现AJAX、JSONP及DOM加载完成事件

一.JS原生Ajax ajax:一种请求数据的方式,不需要刷新整个页面:ajax的技术核心是 XMLHttpRequest 对象:ajax 请求过程:创建 XMLHttpRequest 对象.连接服务器.发送请求.接收响应数据: 下面简单封装一个函数,之后稍作解释 ajax({ url: "./TestXHR.aspx", //请求地址 type: "POST", //请求方式 data: { name: "super", age: 20 },