Twitter引导程序。为什么模式事件在JQuery中起作用,而在纯JS中却不起作用?

问题描述 投票:24回答:2

Twitter Bootstrap模态对话框具有一组可与回调一起使用的事件。

这是jQuery中的一个示例:

    $(modalID).on('hidden.bs.modal', function (e) {

        console.log("hidden.bs.modal");
    });

但是,当我将此方法转录为JS时,事件'hidden.bs.modal'不起作用。使用'click'确实有效:

    document.querySelector(modalID).addEventListener('hidden.bs.modal', function(e) {

        console.log("hidden.bs.modal");
    }, false);

这些Bootstrap事件仅可用于jQuery吗?为什么?

谢谢,道格

javascript jquery twitter-bootstrap-3
2个回答
28
投票

这背后的原因是因为Twitter Bootstrap使用that.$element.trigger('hidden.bs.modal')line 997)来触发其事件。换句话说,它使用.trigger

现在jQuery使用.trigger跟踪每个元素的事件处理程序(所有.on.bind.click等)。这是因为._data被绑定(使用there isn't any other way to get the event handlers)到一个元素。因此,触发方法实际上只是从.addEventListener._data(element, 'events')中获取设置事件侦听器/处理程序作为数组并运行它们中的每一个。

._data(element, 'handle')

handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" ); if ( handle ) { handle.apply( cur, data ); }

这意味着,无论上下文是什么,如果事件通过line 4548绑定,它将不会使用.addEventListener运行。这是一个例子。加载时仅记录.trigger(由jquery触发)。如果单击.trigger元素,则两者都将运行。

a

$('a')[0].addEventListener('click', function(){console.log('addlistener');}, false); $('a').on('click', function(){ console.log('jquery'); }); $('a').trigger('click');

或者,您在DEMO上使用can trigger an event(ie)和fireEvent(non-ie)在javascript中使用元素。 我不一定理解或不知道jQuery的dispatchEvent不这样做的原因,但是他们可能有一个也可能没有。.trigger之后,我发现他们不这样做是因为有些旧的浏览器每个事件仅支持1个事件处理程序。

[通常,我们并未尝试实现仅在某些浏览器(和某些事件)上但不适用于所有浏览器的功能,因为有人会立即提交一个无法正常使用的错误。

尽管我不建议这样做,但是您可以通过对引导程序代码进行最少的更改来解决此问题。您只需要确保下面的功能已附加first(否则您的监听器将触发两次)。

a little more research

最后将Twitter Bootstrap行从上方更改为:

$(modalID).on('hidden.bs.modal', function (e, triggered) {
    var event; // The custom event that will be created

    if(!triggered){
        return false;
    }

    e.preventDefault();
    e.stopImmediatePropagation();

    if (document.createEvent) {
        event = document.createEvent("HTMLEvents");
        event.initEvent("hidden.bs.modal", true, true);
    } else {
        event = document.createEventObject();
        event.eventType = "hidden.bs.modal";
    }

    event.eventName = "hidden.bs.modal";

    if (document.createEvent) {
        this.dispatchEvent(event);
    } else {
        this.fireEvent("on" + event.eventType, event);
    }
});

这是因为您知道它被触发了,而不是您随后自焚的事件。请记住,我还没有尝试使用模态代码。尽管它在下面的that.$element.trigger('hidden.bs.modal', true) 演示中确实可以正常工作,但对于模态它可能无法正常工作。

click


0
投票

本机Javascript解决方案。这是我在没有JQuery的情况下的方法。有点晚了,但是请接受我的代码作为答案。

DEMO

兼容性://my code ---------------------------------------- export const ModalHiddenEventListener = (el, fn, owner) => { const opts = { attributeFilter: ['style'] }, mo = new MutationObserver(mutations => { for (let mutation of mutations) { if (mutation.type === 'attributes' && mutation.attributeName ==='style' && mutation.target.getAttribute('style') === 'display: none;') { mo.disconnect(); fn({ owner: owner, element: mutation.target }); } } }); mo.observe(el, opts); }; //your code with Bootstrap modal id='modal'------- const el = document.getElementById('modal'), onHide = e => { console.log(`hidden.bs.modal`); }; ModalHiddenEventListener(el, onHide, this);

© www.soinside.com 2019 - 2024. All rights reserved.