Twitter Bootstrap。 为什么模态事件在JQuery中工作但在纯JS中不起作用?

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吗? 为什么?

谢谢,
道格

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

现在,jQuery使用._data跟踪每个元素的事件处理程序(所有.on.bind._data等)。 这是因为没有任何其他方法可以将绑定的事件处理程序 (使用.addEventListener )绑定到元素。 所以触发器方法实际上只是将._data(element, 'events')._data(element, 'handle')的set事件监听器/处理程序作为一个数组得到并运行它们中的每一个。

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

( 第4548行 )

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

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

DEMO

或者,您可以使用fireEvent (ie)& dispatchEvent (non-ie)在javascript中触发元素上的事件 。 我不一定理解或知道jQuery的.trigger没有这样做的推理,但他们可能有也可能没有。 经过一番研究后,我发现他们没有这样做,因为一些旧的浏览器每个事件只支持1个事件处理程序。

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

虽然我不推荐它,但你可以通过对bootstraps代码进行少量更改来解决这个问题。 你只需要确保首先附加下面的函数(或者你将有两次触发器)。

 $(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