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