在 JavaScript 中,手动控制事件监听器的顺序

发布于 2024-12-06 18:23:56 字数 1753 浏览 0 评论 0原文

假设 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(),但无法停止传播以防止随后调用 inputLast()

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


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

规则

  1. 以下是

    使用 useCapture=false 触发非目标元素的 ,从最外层元素开始并向目标元素努力

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

  2. 在目标元素处,声明顺序,无论useCapture

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

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

Assuming that FORM contains INPUT, have the following listeners:

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

Desired order of firing

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

Nature of problem and attempted solutions

Own code at FORM level, formFirst, formLast and middle, but have no access to INPUT code, inputFirst and inputLast - although could add own listeners on the INPUT.

Attempt 1 modify formFirst() to create and dispatch a new change Event (would be ignored within formFirst) that would call inputFirst(), but have no way of stopping propagation to prevent inputLast() being called subsequently.

Attempt 2 add middle added as listener to INPUT, but cannot guarantee firing order of two listeners of same type and same useCapture.


Premise of Attempt 2 is incorrect - firing order is determined by declaration order within the target Element.

Here are the rules

  1. non-target Element triggers with useCapture=false, starting at the outermost Element and working toward the target Element

    a) if more than one useCapture=true triggers for same element, then order of declaration.

  2. at target Element, order of declaration, regardless of useCapture

  3. non-target Element triggers with useCapture=false, starting at the innermost Element and working away from the target Element

    a) if more than one useCapture=false triggers for same Element, then order of declaration.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

情话已封尘 2024-12-13 18:23:56

我认为正好回答了您的问题。请随时发表评论\联系我以获取更多信息。

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

好的,我只是按照承诺的那样玩了一下,我发现了一个非常简单的解决方案:

<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 上运行过这个。所以我不想向你保证有关其他浏览器的事情。
  • 另一种方法是自己编写事件处理。这是一个例子。转发这篇文章。

    <脚本类型=“text/javascript”>
    
    函数 formFirst(e) { 警报(1); }
    函数形式mLast(e) { 警报(5); }
    函数 inputFirst(e) { 警报(2); }
    函数 inputLast(e) { 警报(4); }
    函数中间(e){警报(3); }
    
    函数初始化(){
    
      //创建事件
      myHandler = 新事件();
    
      //添加处理程序
      myHandler.addHandler(formFirst);
      myHandler.addHandler(inputFirst);
      myHandler.addHandler(中);
      myHandler.addHandler(inputLast);
      myHandler.addHandler(formLast);
    
      //在某个对象上注册一个监听器
      document.getElementById('input').addEventListener('change',function(){myHandler.execute();},true);
    }
    
    
    函数事件(){
      this.eventHandlers = new Array();
    }
    
    event.prototype.addHandler = 函数(eventHandler){
      this.eventHandlers.push(eventHandler);
    }
    
    event.prototype.execute = function(){
      for(var i = 0; i < this.eventHandlers.length; i++){
        this.eventHandlers[i]();
      }
    }
    
    
    
    
    <表单id=“表单”>
    <输入类型=“文本”id=“输入”/> 
    >

I think that this answers just your question. feel free to comment\contact me for more info.

----- edit ------

OK, I just played with it a little as promised, and I found a very simple solution:

<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>

notice:

  • I put the addEventListener part into an init function, so I can call it after the page is loaded and the element are already exist.
  • I have run this just on chrome. So I don't want to guarantee you things about other browsers.
  • An alternative is writing the event handling on your own. here is an example for that. relaying on this article.

    <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>
    
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文