簡體   English   中英

孩子們如何收聽/捕捉父母的事件

[英]How can the children listen/capture to the parent's event

父母如何觸發自定義事件以通知其孩子/兄弟姐妹? 例如:

<div id="div1">
   <div id="div2"></div>
</div>

div2addEventListener('customEvent2', doSth) ,然后div1將觸發自定義事件( customEvnet2 ),但這永遠不會觸發 div2 的doSth函數。

示例代碼:http: //jsfiddle.net/r4tcT/2/

“div 1 trigger customEvent 2”按鈕永遠不起作用

因此,當父級觸發自定義事件(dispatchEvent[IE9]/fireEvent[IE9-]/trigger[jQuery])時,子級無法捕獲該事件。

有什么解決方法嗎?

您正在談論的區別在於“捕獲”事件模型或“冒泡”事件模型之間。 jQuery 的觸發器在 Bubble 模型上運行可能是因為這是更受支持的事件模型——主要歸功於 Internet Explorer。 Bubble 模型僅通過元素父母向后移動......這就是為什么當從div1觸發時您的事件不會在div2上觸發的原因,因為它總是在冒泡而不是向下。

我之前沒有嘗試使用本機函數自定義事件,但大多數現代瀏覽器允許您在設置事件偵聽器時決定使用哪種類型的模型:

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' );
});

pebbl 的答案很好,但它有缺陷。 捕獲階段是通過從文檔到相關元素的正常觸發事件以某種方式模擬的。 但問題是,在任何元素上調用標准的 jQuery 觸發器函數將立即跟隨從該元素開始的冒泡階段。 所以我相信他可以堅持直接從元素集合中訪問事件數據並直接調用它而不使用標准觸發函數,就像這樣

var JQ_LT_17 = parseFloat($.fn.jquery) < 1.7;

function getEventsData(element) {
        return JQ_LT_17 ? $(element).data('events') : $._data(element).events;
}

代碼片段借用自 jQuery.bind-first library v0.1 Vladimir Zhuravlev

customEvent2僅綁定到div2 當您嘗試在div1上觸發它時,沒有任何反應,因為div1不存在該事件。

如果要觸發customEvent2 ,則必須在它實際綁定的元素(或其中的子元素)上觸發它。

我已經玩了一點代碼,就是我現在擁有的。 這是一個黑客,但也許它可以幫助你解決你的問題?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM