您所讨论的差异是“捕获”事件模型或“冒泡”事件模型之间的差异。 jQuery 的触发器在 Bubble 模型上运行可能是因为这是更受支持的事件模型——主要归功于 Internet Explorer。气泡模型仅通过元素父级向后传播......这就是您的事件不会触发的原因div2
当从div1
,因为它总是向上冒泡而不是向下冒泡。
我之前没有尝试过使用本机函数自定义事件,但大多数现代浏览器允许您在设置事件侦听器时决定使用哪种类型的模型:
addEventListener (type, listener[, useCapture])
https://developer.mozilla.org/en-US/docs/DOM/element.addEventListener
基本上如果你使用true
作为最后一个参数,事件侦听器应在捕获阶段触发(当事件沿着 dom 树传播时)。如果设置为 false,该事件将在冒泡阶段触发,该阶段发生在返回 dom 树时。
这已经在这里讨论过:
事件捕获与事件冒泡
正如我所说,这是否适用于定制活动,我不确定。我很确定你不能用 jQuery 做到这一点(截至目前)可能是由于旧浏览器缺乏支持。
更正
看来我上面的猜测不起作用。我认为“捕获”这个术语会让你考虑捕获用户输入——当涉及定制事件时,没有办法定义一种新的用户输入。因此,考虑到这一点,我组合了这个快速 jQuery 插件...它只是经过了粗略的测试,但逻辑应该是合理的 - 希望它有用:
/**
* unbubble v0.2
*
* trigger an event down through the children of a collection,
* rather than up through it's parents
*
* @update 2013/03/18 - fixed the problem of triggering bubble phase each
* step down the element tree as pointed out by @vine.
*/
$.fn.unbubble = function( eventNames ){
var names = eventNames.split(' '),
non = names.length,
args = Array.prototype.slice.call(arguments);
/// our own trigger function designed to bubble down... not up!
var trigger = function(){
var i, events, elm = $(this);
/// make sure we can read the events array
if ( $._data ) {
/// make sure events is defined
if ( (events = $._data(this, 'events')) ) {
/// do a quick check, saves firing trigger on every element found
for ( i=0; i<non; i++ ) {
/// make sure our eventName appears in the event list
if ( names[i] && ( names[i] in events ) ) {
/// trigger the standard jQuery trigger function
elm.triggerHandler.apply(elm, args);
/// escape as trigger should fire for multiple names
break;
}
}
}
}
/// if we can't access the events array, just trigger and hope
else {
/// trigger the standard jQuery trigger function
elm.triggerHandler.apply(elm, args);
}
/// trigger for all the children, and on, and on...
elm.children().each(trigger);
};
/// foreach element trigger now...
this.each(trigger);
}
/**
* Example usage
*/
$(function(){
/// bind our event as usual
$('.div2').bind('customEvent', function(){
alert('I should trigger!');
});
/// rather than use trigger, fire with unbubble
$('#div1').unbubble( 'customEvent' );
});