【问题标题】:Attaching event in muliple browser在多个浏览器中附加事件
【发布时间】:2019-09-23 15:35:21
【问题描述】:

我有一个函数,我必须在元素 newElement 上附加事件

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 它在 Firefox/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 等,而我不知道哪个函数接受哪些参数。

【问题讨论】:

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


    【解决方案1】:

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

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

    仅供参考,您可以重复使用的通用事件处理函数的工作方式如下:

    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();
    });
    

    【讨论】:

    • 如果我的函数包含一些像这样和其他的参数,我不知道哪个函数接受哪些参数。
    • @Varun - 我不明白你的评论。如果您希望按特定顺序调用函数,请将它们放在一个函数中并一个接一个地调用它们,而不是为它们使用单​​独的事件处理程序。这是执行此操作的安全方法。
    【解决方案2】:

    如果你想在 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();
    }
    

    【讨论】:

    • 如果我的函数包含一些像这样和其他的参数,我不知道哪个函数接受哪些参数。
    • 真的没听懂你在说什么。
    【解决方案3】:

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

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

    【讨论】:

      【解决方案4】:

      使用 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) ;  
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-01-22
        • 1970-01-01
        • 2011-05-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多