在多个浏览器中附加事件

时间:2012-03-15 15:05:56

标签: javascript internet-explorer javascript-events cross-browser

我有一个函数,我必须在元素newElement上附加事件我检查了它的IE或FF是否基于attachEvent proprety(仅适用于IE)

if ( typeof(newElement.attachEvent) != "undefined" )
{               
    newElement.attachEvent("onclick", deleteRow) ;  
    newElement.attachEvent("onclick", customDeleteScript) ;
}else
{   

    newElement.addEventListener("click", deleteRow, false) ;    
    newElement.addEventListener("click", customDeleteScript, false) ;               
} 

首先执行deleteRow所需的流量,然后执行customDeleteScript 它在ff / chrome中工作正常,但IE customDeleteScript中的流量变化在IE中deleteRow之前执行。所以我必须做如下

if ( typeof(newElement.attachEvent) != "undefined" )
{               
    newElement.attachEvent("onclick", customDeleteScript) ;
    newElement.attachEvent("onclick", deleteRow) ;  
}else
{   

    newElement.addEventListener("click", deleteRow, false) ;    
    newElement.addEventListener("click", customDeleteScript, false) ;               
} 

这里的问题在于IE的这个属性,或者它只是IE的随机命中和试用类场景

编辑:如果我的函数包含一些参数,例如this和其他参数,我不知道哪个函数采用哪个参数。

4 个答案:

答案 0 :(得分:1)

如果订单很重要,则不应使用单独的事件处理程序。从一个事件处理程序中按所需顺序调用这两个函数,如下所示:

function delete() {
    deleteRow();
    customDeleteScript();
}

if ( typeof(newElement.attachEvent) != "undefined" )
{               
    newElement.attachEvent("onclick", delete) ;  
}else
{   

    newElement.addEventListener("click", delete, false) ;    
} 

FYI,一个可以重用的通用事件处理函数,如下所示:

function addEvent(elem, event, fn) {
    if (elem.addEventListener) {
        elem.addEventListener(event, fn, false);
    } else {
        elem.attachEvent("on" + event, function() {
            // set the this pointer same as addEventListener when fn is called
            return(fn.apply(elem, arguments));   
        });
    }
}

注意,最好首先检查addEventListener,这样如果两种方法都存在(如IE9),您的代码将采用标准方式。

因此,您的代码可以像这样工作:

addEvent(newElement, 'click', function() {
    deleteRow();
    customDeleteScript();
});

答案 1 :(得分:1)

如果你想在执行deleteRow()之后执行customDeleteScript()函数,你可以在deleteRow()函数的末尾添加一个return true语句,如

function deleteRow()
{
    // other code
    return true;
}

并调用customDeleteScript(),如

if(deleteRow()) customDeleteScript();

你可以使用jfriend00的答案进行事件注册,它更具动态性,并且因为这个原因注册了两个独立的事件处理程序(正如你在问题中描述的那样)并不合适。

更新经过一些研究后,我发现IE为具有多个事件的元素激活已注册的事件处理程序“先进先出(反向顺序)” 。 Try this fiddle in both IE and Chrome/FF。例如

function addEventHandler(to_element,event,handler)
{
    if (to_element.addEventListener) to_element.addEventListener(event,handler,false);
    else if (to_element.attachEvent) to_element.attachEvent("on"+event,handler);
    else return false;
}


function function1()
{
    alert("first alert");
}

function function2()
{
    alert("second alert");
}

var obj=document.getElementById('obj');
addEventHandler(obj,"click",function1);
addEventHandler(obj,"click",function2);​

在Chrome中,将首先触发function1,然后将触发function2 ,但在IE中将首先触发function2,然后触发function1(反向顺序)。因此,根据问题,我认为只应注册一个事件,并在同一个处理程序中调用这两个函数,如

function deleteRow()
{
    // other code here
    return true;
}
function customDeleteScript()
{
    // code here
}
addEventHandler(obj,"click",myHandler);
function myHandler()
{
    if(deleteRow()) customDeleteScript();
}

答案 2 :(得分:0)

你可以通过将这两个处理程序放在一个函数中并将一个函数设置为处理程序来解决它:

function handler() {
    deleteRow();
    customDeleteScript();
}

if (typeof(newElement.attachEvent) != "undefined") {               
    newElement.attachEvent("onclick", handler) ;  
} else {   
    newElement.addEventListener("click", handler, false) ;               
} 

答案 3 :(得分:0)

使用attachEvent附加到同一元素和类型的事件的顺序是保证是它们被声明的顺序。这不是addEventListener的行为,它以声明的顺序执行。如果订单很重要,您可能必须从第一个调用第二个函数,或者将它们合并为一个。

另一个区别是attachEvent会在调用时多次附加相同的处理程序,因此可以多次调用相同的函数,而不是只调用一次。 addEventListener只分配一次,无论你使用相同的参数调用它多少次。

由于IE9 +支持addEventListener,更改分配的顺序,并考虑多个分配(尝试删除不存在的处理程序没有坏处):

if (newElement.addEventListener ){
    newElement.addEventListener("click", deleteRow, false) ;    
    newElement.addEventListener("click", customDeleteScript, false) ;  
}
else if(newElement.attachEvent){   
    newElement.detachEvent("onclick", customDeleteScript) ; 
    newElement.detachEvent("onclick", deleteRow);   
    newElement.attachEvent("onclick", customDeleteScript) ;
    newElement.attachEvent("onclick", deleteRow) ;  
}