事件冒泡存在的原因是为了解决哪个元素是事件的预期目标这一含糊不清的问题。那么,如果您单击一个 div,您是要单击该 div 还是其父级?如果子级没有附加单击处理程序,则会检查父级,依此类推。我相信你知道这是如何运作的。
音频事件不冒泡的原因是它们对任何其他元素都没有意义。当您触发时没有任何歧义timeupdate
在音频元素上,无论它是用于音频元素本身还是其父级 div,因此无需对其进行冒泡。
您可以阅读事件冒泡的更完整历史here
活动委托
通过利用事件的捕获阶段仍然可以进行事件委托。只需添加 true 作为 addEventListener 的第三个参数,如下所示:
document.addEventListener('play', function(e){
//e.target: audio/video element
}, true);
请注意,此事件不会冒泡,而是会沿着 DOM 树向下移动,并且无法通过以下命令停止stopPropagation
.
如果您想将其与 jQuery 的 .on/.off 方法一起使用(例如具有命名空间和其他 jQuery 事件扩展)。以下函数取自网络垫片库,应该变得有用:
$.createEventCapturing = (function () {
var special = $.event.special;
return function (names) {
if (!document.addEventListener) {
return;
}
if (typeof names == 'string') {
names = [names];
}
$.each(names, function (i, name) {
var handler = function (e) {
e = $.event.fix(e);
return $.event.dispatch.call(this, e);
};
special[name] = special[name] || {};
if (special[name].setup || special[name].teardown) {
return;
}
$.extend(special[name], {
setup: function () {
this.addEventListener(name, handler, true);
},
teardown: function () {
this.removeEventListener(name, handler, true);
}
});
});
};
})();
Usage:
$.createEventCapturing(['play', 'pause']);
$(document).on('play', function(e){
$('audio, video').not(e.target).each(function(){
this.pause();
});
});