您正在谈论的区别在于“捕获”事件模型或“冒泡”事件模型之间。jQuery 的触发器在 Bubble 模型上运行可能是因为这是更受支持的事件模型——主要归功于 Internet Explorer。Bubble 模型仅通过元素父母向后移动......这就是为什么您的事件在从 触发div2
时不会触发的原因div1
,因为它总是在冒泡而不是向下。
我之前没有尝试使用本机函数自定义事件,但大多数现代浏览器允许您在设置事件侦听器时决定使用哪种类型的模型:
addEventListener (type, listener[, useCapture])
https://developer.mozilla.org/en-US/docs/DOM/element.addEventListener
基本上,如果您将事件侦听器true
用作最后一个参数,则事件侦听器应在 Capture 阶段(即事件沿 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' );
});