如何在 js 中订购嵌套的事件监听器

How to order nested eventlisteners in js

我的js中有以下代码:

const someElement = document.getElementById('some-element')
    
someElement.addEventListener('click', function(){
        console.log('The start of main event')
    
        const someOtherElement = document.getElementById('some-other-element')
        someOtherElement.addEventListener('load', function () {
            console.log("someOtherElement is invoked")
})
    
        console.log("This is the end of main event")
})

如何使这段代码运行完全按照实际编写代码的顺序。 我想要以下结果:

主赛事开始

someOtherElement 被调用

主赛事到此结束


然而,当代码为 运行 时,我得到以下结果:

主赛事开始

主赛事到此结束

someOtherElement 被调用

之所以这样 运行 是因为这是两个不同的事件 运行 在两个不同的函数中。要解决此问题,您可以使用异步 JavaScript

const someElement = document.getElementById('some-element')

someElement.addEventListener('click', async function(){
  var p = new Promise(function(resolve, fail) {
    console.log('The start of main event')

    const someOtherElement = document.getElementById('some-other-element')
    someOtherElement.addEventListener('load', function () {
      console.log("someOtherElement is invoked")
      resolve(true);
    })
  });
  await p;
  console.log("This is the end of main event")
 })

加载事件只会被调用一次(在您的元素加载之后)。例如,如果您有一个图像并为其放置了加载事件,加载事件将在元素加载后仅触发一次。因此,如果您在some-element some-other-element 已经加载之后单击some-element ,加载事件将不会触发。

此外,如果 some-other-element 在单击 some-element 后加载,它将在 The start of main eventThis is the end of main event 之后记录 someOtherElement invoked

记住: 您只能在 <body><frame><iframe><img><input type="image"><link><script><style> 个标签。

编辑:正如@epascarello在评论中所说,如果你点击some-element多次,它会添加多个事件监听器some-other-element。要解决此问题,您可以使用一个变量:

const someElement = document.getElementById("some-element");
let eventBinded = false;

someElement.addEventListener("click", function () {
    console.log("The start of main event");

    const someOtherElement = document.getElementById("some-other-element");

    if (!eventBinded) {
        eventBinded = true;

        someOtherElement.addEventListener("load", function () {
            console.log("someOtherElement is invoked");
        });
    } else {
        console.log("Event already binded");
    }

    console.log("This is the end of main event");
});