为什么音频和视频事件没有泡沫?

k0p*_*kus 25 javascript audio video html5 javascript-events

我想知道为什么我的一些javascript无法工作,直到我认为音频事件没有冒出DOM树,例如timeupdate-event.

是否有理由不让音频和视频标签的事件冒泡?

sam*_*aml 35

事件冒泡存在的原因是解决了哪个元素是事件的预期目标的模糊问题.那么,如果你点击一个div,你的意思是单击div还是它的父级?如果孩子没有附加点击处理程序,那么它会检查父项,依此类推.我相信你知道这是怎么回事.

音频事件不起泡的原因是因为它们对任何其他元素没有意义.当您触发timeupdate音频元素时,无论是音频元素本身还是其父div,都没有歧义,因此无需冒泡.

您可以在这里阅读更全面的事件冒泡历史

活动代表团

通过利用事件的捕获阶段仍然可以进行事件委派.只需添加true作为addEventListener的第三个参数,如下所示:

document.addEventListener('play', function(e){
    //e.target: audio/video element
}, true);
Run Code Online (Sandbox Code Playgroud)

请注意,此事件不会冒泡,而是沿着DOM树向下,无法停止stopPropagation.

如果您想将此与jQuery的.on/.off方法一起使用(例如,使用命名空间和其他jQuery事件扩展).从webshim库中获取的以下函数应该变得有用:

$.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);
                }
            });
        });
    };
})();
Run Code Online (Sandbox Code Playgroud)

用法:

$.createEventCapturing(['play', 'pause']);

$(document).on('play', function(e){
    $('audio, video').not(e.target).each(function(){
        this.pause();
    });
});
Run Code Online (Sandbox Code Playgroud)

  • 虽然将媒体事件冒泡到其他类型的元素没有多大意义,但是在`body`上注册一个全局事件监听器是有意义的,例如,它将从文档中的任何媒体元素捕获事件. . (21认同)