考虑以下代码示例:
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,以便仅附加一个事件处理程序。
最佳答案
这是委托(delegate)事件处理程序的示例。这个模式非常有用。事实上非常有用,像 jQuery
和 dojo
这样的库已经内置了对这种模式的支持(参见 jQuery.on 和 dojo.on 的 selector
参数) ).
向每个 DOM 节点添加事件处理程序实际上是一个 O(n) 操作,而这是一个 O(1) 操作。随着匹配的 DOM 节点数量的增长,委托(delegate)事件处理程序模式实现了更大的好处。
会出什么问题?
如果在您的顶级元素(在本例中为
window
)和您的目标元素之间附加了一个事件处理程序,并且该事件处理程序执行ev.stopPropagation( )
,那么您的委托(delegate)处理程序将永远不会看到该事件。如果您的过滤器功能过于复杂和缓慢,那么浏览器将不得不花费比平时更多的时间来运行过滤器。
添加事件处理程序后,您将获得添加的 DOM 节点事件。这通常被视为一件好事。但如果出于某种原因你没有预料到它,那么它可能会让你失望。
请注意,在您的特定示例中,实际上注册了两个 click
处理程序。您可以通过 share
将其缩减为单个实例:
var allClicks_ = Observable.fromEvent(window, 'click').share();
关于javascript - 过滤窗口上的事件与 DOM 节点上的单个事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30740729/