【问题标题】:Twitter Bootstrap. Why do modal events work in JQuery but NOT in pure JS?推特引导。为什么模态事件在 JQuery 中有效,但在纯 JS 中无效?
【发布时间】:2014-08-04 08:37:31
【问题描述】:

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


    【解决方案1】:

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

    现在 jQuery 使用 ._data 跟踪每个元素的事件处理程序(所有 .on.bind.click 等)。这是因为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 使用 fireEvent(ie) 和 dispatchEvent(non-ie) 在 javascript 中的元素上。 我不一定理解或知道 jQuery 的.trigger 不这样做的原因,但他们可能有也可能没有。a little more research 之后我发现他们没有这样做因为一些较旧的浏览器仅支持每个事件 1 个事件处理程序。

    一般来说,我们并未尝试实现仅适用于某些浏览器(和某些事件)但并非全部适用的功能,因为有人会立即提交一个无法正常工作的错误。

    虽然我不建议这样做,但您可以通过对引导程序代码进行少量更改来解决此问题。您只需要确保 first 附加了下面的函数(否则您将让侦听器触发两次)。

    $(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);
        }
    });
    

    最后将上面的 Twitter Bootstrap 行改为:

    that.$element.trigger('hidden.bs.modal', true)
    

    这是为了让你知道它被触发了,而不是你自己触发的事件。请记住,我没有在模态中尝试过这段代码。虽然它在下面的click 演示中运行良好,但它可能会或可能不会像预期的那样在模态中运行。

    DEMO

    【讨论】:

    • 老兄,那是史诗。我是 JS 的新 iOS 开发人员,所以我的想法很合适。对于这个项目,我必须尽可能使用纯 JS。什么是纯JS相当于你的精彩论文?干杯。
    【解决方案2】:

    原生 Javascript 解决方案。这是我在不使用 JQuery 的情况下的做法。

    //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);
    

    兼容性: https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver/observe#Browser_compatibility

    【讨论】:

    • 我完全确定您是 JS Vanilla 大师。祝贺这个解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-12
    相关资源
    最近更新 更多