考虑以下代码示例:
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”,而是向窗口添加了事件侦听器并过滤了“ .red”和“ .blue”上的事件.
现在这样的代码会出什么问题?它比向单个DOM节点添加事件侦听器更有效(或更低)?还是没有性能优势?
编辑:共享热的Observable,以便仅附加一个事件处理程序.
解决方法:
这是委托事件处理程序的示例.此模式非常有用.实际上如此有用,以至于jQuery和dojo之类的库都对此模式提供了内置支持(请参见jQuery.on和dojo.on的选择器参数).
向每个DOM节点添加事件处理程序实际上是O(n)操作,而这是O(1)操作.随着匹配的DOM节点数量的增加,委托事件处理程序模式实现了更大的收益.
有什么问题吗?
>如果在*元素(在本例中为窗口)和目标元素之间附加了事件处理程序,并且该事件处理程序执行ev.stopPropagation(),则委派的处理程序将永远不会看到该事件.
>如果您的过滤器功能过于复杂和缓慢,则浏览器将比平时运行过滤器花费更多的时间.
>在添加事件处理程序之后,您将获得针对DOM节点添加的事件.通常认为这是一件好事.但是,如果由于某种原因而没有想到,它可能会把您扔掉.
请注意,在您的特定示例中,实际上正在注册两个点击处理程序.您可以通过共享将其简化为单个实例:
var allClicks_ = Observable.fromEvent(window, 'click').share();