setTimeout 干扰加载事件处理程序的问题

Issues with setTimeout interfering with load event handler

我在 <track> 元素上附加了一个 load 事件处理程序。我怎样才能确保处理程序被调用,即使它是在 <track> 已经加载之后附加的?

例如

track.addEventListener('load', function () {
    //this should get called even if the track has already loaded
});

您的代码运行良好,如下所示。我只是将事件从加载更改为单击并在 foo 之前添加了功能词。

function foo(div) {
  div.addEventListener('click', function() {
    console.log('this loads');
  });
};


var div = document.getElementById('main');
  
setTimeout(function() {
  foo(div);
}, 1000);
#main {
  background-color: red;
  width: 100px;
  height: 100px;
}
<div id="main"></div>

请注意,load 事件不会在 chromium 上触发,chrome 如果 default 属性未在 <track> 元素上设置。

不确定您是在更改现有 <track> 元素的 src 还是将新的 <track> 元素附加到父 <video> 元素?

下面的方法将新的 <track> 元素附加到 <video> 元素。将 src 传递给 foo,在附加到父 <video> 元素之前将 load 事件附加到 track 元素,将 <track> 元素附加到 <video> 元素,然后将 src 设置为传递给 foo

的变量
window.onload = function() {

  // append next `track` element to `video` in 1 seconds
  setTimeout(function() {
    // pass `src`, `label` to set at `track` element
    addTrack("/path/to/resource2", "track 1") 
  }, 1000);

  function foo(track, src) {  
    track.addEventListener("load", function() {
      console.log("this loads");
    });
    video.appendChild(track);
    track.src = src;
  };

  function addTrack(src, tracklabel) {
    var track = document.createElement("track");
    track.kind = "captions";
    track.srclang = "en";
    track.label = tracklabel;
    // set `default` attribute at `track` element
    track.setAttribute("default", "default");
    // pass `track` element, `src` to set at `track` to `foo`
    foo(track, src);
  }

  addTrack("/path/to/resource1", "track 1");

}

如果事件在没有附加侦听器时触发,则事件丢失。希望 HTMLTrackElement 有一个 readyState 属性 可以检查它以了解加载状态。

像这样的东西应该可以工作,它附加处理程序来处理后续的加载事件,如果曲目当前已加载,它也会立即调用回调。

function whenLoaded(track, callback) {
    const LOADED = 2;

    track.addEventListener('load', callback);
    if (track.readyState === LOADED) callback();
}

来自您的后续评论:

the goal is to have this function work with content being added dynamically.

使事件侦听器处理动态内容的最佳解决方案是事件委托。不必担心在添加该元素后将事件侦听器添加到动态元素,您只需将事件侦听器添加到该元素的 parent,其中 parent 元素已存在于文档中。或者您可以使用 grandparent、great-grandparent 等。如果没有更具体的元素可以使用,您甚至可以一直使用 body 元素。

您可以在加载动态内容之前添加此事件侦听器,因为您将它添加到一个已经存在的元素上。

调用事件侦听器时,event.target 是对触发事件的实际元素的引用。所以你检查它是否是你想要实际处理事件的元素之一。

this question 的答案有一些关于如何使用事件委托的很好的例子。它非常简单,并解决了在动态添加的内容上监听事件的所有问题。