最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Javascript event listener - run code after event finish bubbling - Stack Overflow

programmeradmin6浏览0评论

I would like to run some code after event finish to bubble up the DOM for example

    document.getElementById("myBtn").addEventListener("click", (event) => {
       // run some code after event finish to bubble up
});

I would like to run some code after event finish to bubble up the DOM for example

    document.getElementById("myBtn").addEventListener("click", (event) => {
       // run some code after event finish to bubble up
});
Share Improve this question asked May 10, 2017 at 7:04 user1116377user1116377 6993 gold badges15 silver badges32 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 5

You have at least two choices:

  1. Queue an async task (setTimeout or a Promise resolution)

  2. Handle the event on document, but only if it passed through #myBtn en route to it; this isn't technically when it's fully pleted bubbling, just at the final stage of it

Note that some actions that must be in response to a user event (such as opening a window) may or may not work with #1.

Here's #1 using a Promise:

document.getElementById("myBtn").addEventListener("click", (event) => {
    Promise.resolve().then(() => {
        // Do the work here
    });
});

The advantage to using a promise resolution is that on pliant browsers, the promise resolution will be run before any other queued events. (Promise resolutions are microtasks that run after the current task but before the next task.) So it'll run before any event handler callback for elements the event bubbles to. But that may not fit your definition of "after event finish bubble up the DOM." If not, use setTimeout instead, because it queues a task (not a microtask):

Here's an example of both:

document.getElementById("promiseButton").addEventListener("click", (event) => {
    console.log(`button click on #${event.currentTarget.id}`);
    Promise.resolve().then(() => {
          console.log("promise fulfillment");
    });
});
document.getElementById("timeoutButton").addEventListener("click", (event) => {
    console.log(`button click on #${event.currentTarget.id}`);
    setTimeout(() => {
          console.log("timer callback");
    }, 0);
});
document.addEventListener("click", (event) => {
    console.log("document click");
});
<input type="button" id="promiseButton" value="Using promise">
<input type="button" id="timeoutButton" value="Using setTimeout">

Here's #2:

document.addEventListener("click", (event) => {
    const node = event.target.closest("#myBtn");
    if (node) {
        // Do the work here
    }
});

Note that if the event is handled before it bubbles to the document and the handler uses stopPropagation, you won't see the event (since that stops it bubbling to the document). Here's an example of both when it reaches the document and when it doesn't:

document.getElementById("workedButton").addEventListener("click", (event) => {
    console.log(`button click on #${event.currentTarget.id}`);
});
document.getElementById("blockedButton").addEventListener("click", (event) => {
    console.log(`button click on #${event.currentTarget.id}`);
});
document.getElementById("blocker").addEventListener("click", (event) => {
    console.log("blocked");
    event.stopPropagation();
});
document.addEventListener("click", (event) => {
    const node = event.target.closest("#workedButton, #blockedButton");
    if (node) {
        console.log(`document click on #${node.id}`);
    }
});
<input type="button" id="workedButton" value="Works">
<div id="blocker">
    <input type="button" id="blockedButton" value="Blocked">
</div>

Then you should add an event listener to the document object, that is the last DOM "element" that recognizes an event, all of the events will have bubbled up to document.

发布评论

评论列表(0)

  1. 暂无评论