2015-06-09 84 views
3

考慮下面的代碼示例:過濾事件節點

import R from 'ramda'; 
import {Observable} from 'Rx'; 

var allClicks_ = Observable.fromEvent(window, 'click').share(); 

var getClicks = function(klass) { 
    return allClicks_.filter(e => { 
    return R.contains(klass, e.target.classList); 
    }); 
}; 

getClicks('red').subscribe(x => { 
    render('RED: ' + x.target.className); 
}); 

getClicks('blue').subscribe(x => { 
    render('BLUE: ' + x.target.className); 
}); 

而不是增加點擊事件偵聽器「.red」和「的.blue」,我添加了一個事件監聽器window並過濾「.red」和「.blue」上的事件。

現在有什麼可以出現這樣的代碼錯?它是否比將事件偵聽器添加到單個DOM節點更高效(或更低效率)?或者它沒有性能優勢?

編輯:共享熱的Observable,所以只附加一個事件處理程序。

回答

3

這是一個委託事件處理程序的示例。這種模式非常有用。實際上,像jQuerydojo這樣的庫對此模式具有內置支持(請參閱jQuery.ondojo.onselector參數)非常有用。

向每個DOM節點添加事件處理程序實際上是O(n)操作,而這是O(1)操作。隨着匹配DOM節點數量的增長,委託事件處理程序模式實現了更大的優勢。

什麼可以出錯?

  • 如果附加了頂層元素(window在這種情況下),你的目標元素之間的事件處理程序,該事件處理程序做了ev.stopPropagation(),那麼你的委託處理程序將永遠不會看到該事件。

  • 如果你的過濾功能過於複雜和慢,那麼瀏覽器將不得不花費比平時運行過濾器更多的時間。

  • 您將在添加事件處理程序後,在之後爲DOM節點添加事件。這通常被看作好東西。但如果由於某種原因,你不期待它,那麼它可能會拋出你。

注意,在你的具體的例子是在實際註冊 click處理程序。您可以通過share將其減少到一個實例:

var allClicks_ = Observable.fromEvent(window, 'click').share(); 
+0

感謝您分享熱的Observable。我正在考慮創建一個小應用程序,以採用兩種方法進行基準測試但是......也許以後。 – channikhabra