javascript - 过滤窗口上的事件与 DOM 节点上的单个事件

标签 javascript rxjs

考虑以下代码示例:

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)事件处理程序的示例。这个模式非常有用。事实上非常有用,像 jQuerydojo 这样的库已经内置了对这种模式的支持(参见 jQuery.ondojo.onselector 参数) ).

向每个 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/

相关文章:

javascript - 如何使用 jQuery/Ajax 将数据传递到 URL

javascript - 如何为嵌套对象使用 javascript 代理

javascript - 过滤对象数组的一部分的更有效方法?

angular - RXJS 如何在另一个中使用一个 observable 的结果(然后将这两个结果一起处理)

angular - RxJs 组合 Observable

javascript - 我如何实现 Angular2 时钟

javascript - 将一系列有序操作组合成一个 Observable

asp.net - 有没有办法在 javascript 中设置 asp.net 按钮的 CommandArgument?

angular - Angular 如何处理异步初始化的属性?

javascript - 如果在 moment.js 的最后一周内使用 "5 days ago (Tue)"