【问题标题】:in javascript, manually controlling order of event listeners在 javascript 中,手动控制事件监听器的顺序
【发布时间】:2011-11-25 00:28:23
【问题描述】:

假设 FORM 包含 INPUT,有以下监听器:

javascript

function formFirst(e) { ... }
function formLast(e) { ... }
function inputFirst(e) { ... }
function inputLast(e) { ... }
function middle(e) { ... }

document.getElementById('form').addEventListener('change',formFirst,true);
document.getElementById('form').addEventListener('change',formLast,false);
document.getElementById('input').addEventListener('change',inputFirst,true);
document.getElementById('input').addEventListener('change',inputLast,false);

所需的发射顺序

formFirst()   // normal - outer element, useCapture = true
inputFirst()  // normal - triggering element, declared first
middle()      // -- how to do this?
inputLast()   // normal - triggering element, declared second
formLast()    // normal - outer element, useCapture = false

问题的性质和尝试的解决方案

在 FORM 级别拥有自己的代码 formFirstformLastmiddle,但无法访问 INPUT 代码 inputFirstinputLast - 尽管可以在 INPUT 上添加自己的侦听器。

尝试 1 修改 formFirst() 以创建并调度一个新的 change Event(将在 formFirst 中被忽略),该 inputFirst() 将调用 inputFirst(),但无法停止传播以防止inputLast() 随后被调用。

尝试2middle添加为INPUT的侦听器,但不能保证两个相同类型和相同useCapture的侦听器的触发顺序。


尝试 2 的前提不正确 - 触发顺序由目标元素内的声明顺序决定。

这里是规则

  1. 非目标元素触发useCapture=false,从最外层元素开始,朝着目标元素前进

    a) 如果多个useCapture=true 触发同一元素,则声明顺序。

  2. 在目标元素处,声明顺序,不管useCapture

  3. 使用useCapture=false 触发非目标元素,从最里面的元素开始,远离目标元素

    a) 如果多个useCapture=false 触发同一个元素,则声明顺序。

【问题讨论】:

    标签: javascript dom javascript-events


    【解决方案1】:

    我认为this 只是回答了您的问题。随时发表评论\联系我了解更多信息。

    ----- 编辑 ------

    好的,我只是按照承诺玩了一点,我找到了一个非常简单的解决方案:

    <script type="text/javascript">
    function formFirst(e) { alert(1); }
    function formLast(e) { alert(5); }
    function inputFirst(e) { alert(2); }
    function inputLast(e) { alert(4); }
    function middle(e) { alert(3); }
    
    function init(){
        document.getElementById('form').addEventListener('change',formFirst,true);
        document.getElementById('form').addEventListener('change',formLast,false);
        document.getElementById('input').addEventListener('change',inputFirst,true);
        document.getElementById('input').addEventListener('change',middle,true);
          /*** alternative to last tow lines  
        document.getElementById('input').addEventListener('change',function(){inputFirst();middle();},true);
             **/
        document.getElementById('input').addEventListener('change',inputLast,false);
    }
    
    </script>
    <body onload="init();">
    <form id="form">
    <input type="text" id="input" /> <br />
    </form>
    </body>
    

    注意:

    • 我把addEventListener部分放到了一个init函数中,这样我就可以在页面加载完毕并且元素已经存在之后调用它。
    • 我只在 chrome 上运行过它。所以我不想向你保证关于其他浏览器的事情。
    • 另一种方法是自己编写事件处理。这是一个例子。转发this 文章。

      <script type="text/javascript">
      
      function formFirst(e) { alert(1); }
      function formLast(e) { alert(5); }
      function inputFirst(e) { alert(2); }
      function inputLast(e) { alert(4); }
      function middle(e) { alert(3); }
      
      function init(){
      
        //create event
        myHandler = new Event();
      
        //add handler
        myHandler.addHandler(formFirst);
        myHandler.addHandler(inputFirst);
        myHandler.addHandler(middle);
        myHandler.addHandler(inputLast);
        myHandler.addHandler(formLast);
      
        //regiser one listener on some object
        document.getElementById('input').addEventListener('change',function(){myHandler.execute();},true);
      }
      
      
      function Event(){
        this.eventHandlers = new Array();
      }
      
      Event.prototype.addHandler = function(eventHandler){
        this.eventHandlers.push(eventHandler);
      }
      
      Event.prototype.execute = function(){
        for(var i = 0; i < this.eventHandlers.length; i++){
          this.eventHandlers[i]();
        }
      }
      
      
      </script>
      <body onload="init();">
      <form id="form">
      <input type="text" id="input" /> <br />
      </form>
      </body>
      

    【讨论】:

    • 对于您的具体示例,只需使用 'ture' 作为所有事件侦听器的第三个参数。
    • 从我的测试中我认为你是不正确的。如果formLastuseCapture = true 一起添加,则formLast 将在 INPUT 触发器之前触发,而不是像现在这样跟随它们。
    • 你是对的。没想到扔了试试this article,您可以在那里创建自己的处理程序。而且我还没有尝试过(只是找到了)。但我想您可以将中间函数附加到触发inputFirst 函数的事件处理程序,以便处理程序稍后触发中间方法。我会在晚上玩那个选项。所以,如果这仍然不起作用,请告诉我。
    • 很抱歉花了这么长时间才回来 - 搬家。你是对的 - 创建侦听器的顺序决定了 target 内的触发顺序 - 尽管 true 触发器应该在 false 之前触发是有道理的,因为在非目标上,情况并非如此.
    • 你好。几天前我读了一些关于 jQuery 的东西,它不是你想要的,但可以提供帮助。因为有一个callback 选项。这意味着您调用一个方法并在回调中发送下一个方法(创建执行链)。如果以某种方式同时触发类似的拖曳场,则可能会出现问题。但在change 事件中,我对此表示怀疑。
    猜你喜欢
    • 1970-01-01
    • 2013-08-16
    • 2012-03-19
    • 2012-09-13
    • 1970-01-01
    • 2020-06-21
    • 1970-01-01
    • 2016-10-15
    相关资源
    最近更新 更多