如何确保最后执行EventListener?

时间:2017-12-17 23:26:54

标签: javascript dom addeventlistener dom-events

我想要一个特定的EventListener,我添加到EventTarget最后执行(但在默认操作之前),与中注册的顺序无关,还有一个额外的约束,即事件不可取消,意味着它只能被触发一次才能达到这个目的。

我已经尝试在事件侦听器中使用.addEventListener,但这只会注册一个EventListener,以便在下次发生事件时执行,而不是在当前处理期间执行。 不幸的是,EventListenerList永远不会成为DOM规范的一部分,这意味着它也不是使用.stopImmediatePropagation并在执行最后要执行的操作之前手动执行其他事件的选项。

我不是在寻找它们执行的顺序,我知道现代浏览器引擎按注册顺序执行EventListeners。我问的是绕过这种行为的方法(可能只是结果)。

对此的特定需求是在内容脚本中(意味着我无法控制添加的其他EventListener(或发生的顺序))在使用它们之前重写URL - 但是某些页面具有EventListeners在同一事件中他们自己的改写。

当前行为的一个示例:

// The content script:
document.getElementById("target").addEventListener("click",last);

function last() {
  this.innerHTML="Correct!";
  console.log("This is supposed to occur last.")
}


// The webpage:
document.getElementById("target").addEventListener("click",first);

function first() {
  this.innerHTML="Incorrect!";
  console.log("This is supposed to occur first.")
}
<button id="target">
Click me!
</button>

2 个答案:

答案 0 :(得分:1)

替代方案可能是处理所有点击事件并检查event.target是否是要处理的元素:

function first() { console.log('first') }
function second() { console.log('second') }
function last(e) { if (e.target.id === 'target') console.log('last') }

target.addEventListener("click", first);
document.body.addEventListener("click", last);
target.addEventListener("click", second);
<button id="target">
  Click me!
</button>

由于事件冒泡,按钮事件在其父事件之前执行。

答案 1 :(得分:0)

实现此目的的一个简单但绝不是完全合理的方法是将最后要发生的事件包装在setTimeout()中。这将导致执行延迟。当然,如果在其他事件侦听器中存在异步的其他函数,则可能无法完全预测所需的延迟:

function last() {
  setTimeout( () => {
   this.innerHTML=("Correct!");
   console.log("This is supposed to occur last.")
  })
}


// The webpage:

document.getElementById("target").addEventListener("click",last);
document.getElementById("target").addEventListener("click",first);



function first() {
  this.innerHTML="Incorrect!";
  console.log("This is supposed to occur first.")
}
<button id="target">
Click me!
</button>