日期:2014-05-16  浏览次数:20382 次

在JS 中动态添加事件

在 JS 中动态添加事件,涉及到浏览器兼容性问题。结合我的实践经验以及从网上收集的一些资料,特整理在此,希望有点用。
?function document.oncontextmenu() {
?? ...............
};

等价与:

document.oncontextmenu = function() {
???? ..................
}

等价于:

function XX() {
?? ...............
};

document.oncontextmenu = XX;

等价于:

var functionPointer = function() {
?? .............
}

document.oncontextmenu = functionPointer;

这是一个典型的观察者模式, 当你点击右键时,IE(仅仅IE)会触发一个消息(事件),这个消息被发给当前的文档上下文,而这个文档上下文的消息循环收到这个消息后,就调用oncontextmenu指定的函数地址。

事件是通过一个链子来传递的, 最原始的事件由操作系统控制,当点击鼠标右键时,触发一个WM_MOUSE消息(以windows为例子),这个消息首先会被浏览器截取,浏览器再通知到DOM对象,而DOM再通知给你绑定的这个JS, 如果你设置了contextnenu返回了false的话,该链子就会终止,而导致浏览器不会去调用其事件回调函数去处理这个事件了。
方法一、setAttribute
var obj = document.getElementById("obj");
obj.setAttribute("onclick", "javascript:alert('测试');");//引号括起
这里利用 setAttribute 指定 onclick 属性, 但是:用 setAttribute 设置 style、onclick、onmouseover 这些属性在 IE 中是行不通的。但是某些属性可以,以下是通过测试的一个例子:
如果你知道某个控件如select控件的name,但是这个控件并没有设置id属性,这时候在IE下测试发现如果仅仅通过控件的name是无法给它动态添加属性和事件的,因为W3C是允许name属性重复的。
function test(){
??? //通过tag,获得所有tagName为select的控件,返回的是一个select集合
var obj=document.getElementByTagName(“select”);
//通过obj.length获得select集合的个数,在挨个匹配name
for(var i=0;i<obj.length;i++){
?? //找到name为part的select控件
?? if(obj[i].name==’part’){
??????? obj[i].setAttribute(“id”,”myid”);//为name为part的select控件设置id为myid
??????? obj[i].setAttribute(“onchange”,myfunc); //为该控件设置onchange事件,即调用myfunc函数,调用函数只是名称,没有引号且没有参数
}
}
}
?
function myfunc(){
?? alert(“test ok!”);
}

方法二、用 attachEvent 和 addEventListener
IE支持attachEvent
obj.attachEvent("onclick", Foo);
function Foo()
{
??? alert("测试");
}
也可写在一起
obj.attachEvent("onclick", function(){alert("测试");});//匿名函数没有引号且没有参数

但是不能这样写

obj.attachEvent("click", alert("测试"));//不能是语句必须是函数名称,或者匿名函数

其它浏览器支持 addEventListener
obj.addEventListener("click", Foo, false);
function Foo()
{
??? alert("测试");
}
同样也可写在一起

obj.addEventListener("click", function(){alert("测试");}, false);//匿名函数无须引号括起

但是不能这样写

obj.addEventListener("click", alert("测试"), false);//不能是语句必须是函数名称,或者匿名函数,如果是语句就只是在加载页面的时候执行一次,以后单击会触发事件但不会再执行这条语句了。


注意 attachEvent 的事件带 on,如 onclick,而 addEventListener 不带 on,如 click。
顺便说一下 addEventListener 的第三个参数(虽然很少用) useCapture - 如果为 true,则 useCapture 指示用户希望启动捕获。启动捕获后,所有指定类型的事件将在被指派到树中其下面的任何 EventTargets 之前指派给已注册的 EventListener。正在通过树向上 bubbling 的事件将不触发指定的使用捕获的 EventListener。
综合应用
var obj = document.getElementById("obj");
?if(window.addEventListener){
//其它浏览器的事件代码: Mozilla, Netscape, Firefox
//添加的事件的顺序即执行顺序
??????? obj.addEventListener('click', function(){alert('test1');}), false);
??????? obj.addEventListener('click', function(){alert('test2');}), false);
?? } else {
//IE 的事件代码
??????? obj.attachEvent('onclick',? function(){alert('test3');});
??????? obj.attachEvent('onclick