自己封装的javascript事件队列函数版
自己封装的javascript事件队列函数版
发布时间:2016-12-30 来源:查字典编辑
摘要:背景javascript中使用addEventListener()或attachEvent()绑定事件时会有几个小问题:一、使用addEve...

背景

javascript中使用addEventListener()或attachEvent()绑定事件时会有几个小问题:

一、使用addEventListener()或attachEvent()添加的匿名函数无法移除。

复制代码 代码如下:var oBtn = document.getElementById('btn');

oBtn.addEventListener('click',function(){

alert('button is clicked')

},false)

oBtn.reomveEventListener('click',function(){

alert('button is clicked')

},false)

//oBtn上的事件无法移除,因为传入的是一个匿名函数

二、ie6-ie8中,使用attachEvent()绑定多个事件的倒序执行问题。

复制代码 代码如下:

var oBtn = document.getElementById('btn');

oBtn.attachEvent('onclick',function(){

alert(1)

})

oBtn.attachEvent('onclick',function(){

alert(2)

})

oBtn.attachEvent('onclick',function(){

alert(3)

})

//ie9+ 下执行顺序1、2、3

//ie6-ie8下执行顺序3、2、1

解决问题

我想写一个跨浏览器的事件绑定模块,这样以后可以复用,同时我想解决上诉问题。JQuery内部使用事件队列和数据缓存机制解决此问题,看了下相关源码,实在复杂,自个试了一些方法,勉强实现。贴段代码,原来是用面向对象写的,不想让人看得很复杂,所有改成函数来组织。

复制代码 代码如下:

/*绑定事件的接口

*

*@param {dom-DOM}和{type-string}和{fn-function} 可选参数{fnName-string}

*@execute 创建事件队列,添加到DOM对象属性上,

将事件处理程序(函数)加入事件队列

可为事件处理程序添加一个标识符,用于删除指定事件处理程序

*/

function bind(dom,type,fn,fnName){

dom.eventQueue = dom.eventQueue || {};

dom.eventQueue[type] = dom.eventQueue[type] || {};

dom.handler = dom.handler || {};

if (!fnName) {

var index = queueLength(dom,type);

dom.eventQueue[type]['fnQueue'+index] = fn;

}

else {

dom.eventQueue[type][fnName] = fn;

};

if (!dom.handler[type]) bindEvent(dom,type);

};

/*绑定事件

*

*@param {dom-DOM}和{type-string}

*@execute 只绑定一次事件,handler用于遍历执行事件队列中的事件处理程序(函数)

*@caller bind()

*/

function bindEvent(dom,type){

dom.handler[type] = function(){

for(var guid in dom.eventQueue[type]){

dom.eventQueue[type][guid].call(dom);

}

};

if (window.addEventListener) {

dom.addEventListener(type,dom.handler[type],false);

}

else {

dom.attachEvent('on'+type,dom.handler[type]);

};

};

/*移除事件的接口

*

*@param {dom-DOM}和{type-string} 可选参数{fnName-function}

*@execute 如果没有标识符,则执行unBindEvent()

如果有标识符,则删除指定事件处理程序,如果事件队列长度为0,执行unBindEvent()

*/

function unBind(dom,type,fnName){

var hasQueue = dom.eventQueue && dom.eventQueue[type];

if (!hasQueue) return;

if (!fnName) {

unBindEvent(dom,type)

}

else {

delete dom.eventQueue[type][fnName];

if (queueLength(dom,type) == 0) unBindEvent(dom,type);

};

};

/*移除事件

*

*@param {dom-DOM}和{type-string}

*@execute 移除绑定的事件处理程序handler,并清空事件队列

*@caller unBind()

*/

function unBindEvent(dom,type){

if (window.removeEventListener) {

dom.removeEventListener(type,dom.handler[type])

}

else {

dom.detachEvent(type,dom.handler[type])

}

delete dom.eventQueue[type];

};

/*判断事件队列长度

*

*@param {dom-DOM}和{type-string}

*@caller bind() unBind()

*/

function queueLength(dom,type){

var index = 0;

for (var length in dom.eventQueue[type]){

index++ ;

}

return index;

};

使用方法

复制代码 代码如下:

var oBtn = document.getElementById('btn');

//绑定事件

//为button同时绑定三个click事件函数

//ie6-ie8下执行顺序不变

bind(oBtn,'click',function(){

alert(1);

})

bind(oBtn,'click',function(){

alert(2);

},'myFn')

bind(oBtn,'click',function(){

alert(3);

})

//移除事件

//移除所有绑定的click事件函数,支持移除匿名函数

unBind(oBtn,'click')

//只移除标识符为myfn的事件函数

unBind(oBtn,'click','myFn')

程序思路

程序主要思路就像将事件队列作为dom元素对象的一个属性,添加在dom元素上,而不会污染全局环境,这样可以解决不同dom元素绑定不同事件类型的多个事件函数的数据存储问题。

复制代码 代码如下:

//dom元素上的事件队列

dom{

eventQueue : {

'click' : {

fnQueue1 : function,

myfn : function,

fnQueue3 : function

}

'mouseover' : {

fnQueue1 : function,

fnQueue2 : function

}

}

}

每次先把事件函数添加到对应事件类型的事件队列中,只绑定一次事件。触发事件时执行handler事件函数,handler则遍历执行事件队列中的事件函数。

unBind()如果没有传入标识符,则移除所有绑定的事件函数,支持移除匿名函数,如果有标识符则移除指定的事件函数。

程序逻辑并不复杂,可能有bug和性能问题,有兴趣可以指导交流下。

推荐文章
猜你喜欢
附近的人在看
推荐阅读
拓展阅读
相关阅读
网友关注
最新Javascript教程学习
热门Javascript教程学习
编程开发子分类