事件代理 | Event Delegation

/ 0评 / 0

有些东西是你一直在用却一直没有发觉,直到别人提起你才会意识到——嗷,原来这些理所当然的事情背后还有原因。

事件代理对于前端开发来说是一个每天都在用但是如果不去详细了解就完全不会知道这个名词的东西。它的核心思想是:为每一个控件都设置事件处理器的开销有些过分的大而且烦人,我们应该归并那些相似的事件一并交由上层处理。

一个典型的例子就是……快递。尽管几乎所有人谈论事件代理的时候都是用这个例子的,但是这无疑是最生动最形象同时最贴近生活的例子。在没有事件代理的情况下,所有人都在等快递,没人去工作。这显然是不合适的。那么,从中选出一个人作为前台负责收取所有人的快递,再将快递分发给对应的人,剩下的人就可以去做其他事情了。对于新加入这个组织的人,前台也可以帮助他们收取快递。这突出了事件代理的两个能力:归并相似事件处理函数、为新的成员添加事件处理而无需显式注册。

那么,如何实现这样一个功能呢?

首先,这个功能需要保证事件是可以冒泡的——来自子组件的事件可以逐步传递给父组件进行处理。这也暗示着组件之间是有从属结构的。同时我们希望有些事件可以冒泡、有些不能。所有这些功能,都可以简单地完成:

const Component = function (parent = undefined) {
  this.parent = parent;
  this.eventHandlers = {};
  this.addEventHandler = (ev, cb) => {
    const handlers = this.eventHandlers[ev] || [];
    handlers.push(cb);
    this.eventHandlers[ev] = handlers;
  };
  this.triggerEvent = (e) => {
    (this.eventHandlers[e.type] || []).forEach(it => {
      it(e);
    });
    if (e.bubble && this.parent != null) {
      this.parent.triggerEvent(e);
    }
  };
};

有些令人意外得直白——这也确实不是什么特别复杂的功能,只是由于过于 trivial, 所以我们一直没有提起。


谨以此文献给暴毙的笔试。

发表评论

电子邮件地址不会被公开。 必填项已用*标注