jQuery event 分析

jQuery event 相关

核心方法 \$.fn.on/off
其他, bind/one/delegate 啥的都是调这个

[TOC]

\$.event

包含几个静态方法 add/remove/fix …
实际工作由这里的方法完成

\$.Event

这是 jQuery Event class,jQuery 事件系统中的 event 对象是这个类的实例

  • originalEvent 原来的 DOM 事件
  • delegateTarget delegate 到的 target,例如
    1
    2
    3
    4
    5
    $(document).on('click','.some-class',function(e){
    /
    e.delegateTarget === document; // true
    $(e.currentTarget).hasClass('some-class'); // true
    });

\$.fn.on

syntax: on(event,selector,data,handler)

前面说了\$.data , 那个 cache 结构

1
2
3
4
5
6
7
id = elem[$.expando];
cache = $.cache[id] = {
data: {
// 这是 $.fn.data , $.data 操作的地方
}
// 内部 internal private 数据 如 parsedAttrs
};

现在发现,这个内部 internal 数据,包括很多,其中就有 event system 的数据
在 jQuery.event.add 里面的 elemData 就是这里说的 cache.

其中

  • handler 是 add 方法内部的一个函数,用以调用 \$.event.dispatch
  • events 就是 pub/sub 模式的注册表喽,常见的 EventEmitter 实例的 this._events

event namespace

没看懂 event 的 namespace 到底怎么搞的,为啥要 sort ???

namespace 使用

拿 bootstrap 的说吧,这里的 event 可以带 namespace

  1. on(event,selector,handler)
  2. trigger(event)
  3. off(event)
1
2
3
4
$(document).on('click.bs.modal.data-api', '[data-toggle="modal"]',
function (e) {
// handler
}

这里只要写上 [data-toggle=modal] 的,click 会调用 modal 对话框.在 event 里面直接写 click 也是可以的,但是有 namespace 就可以

  • 根据 namespace 至调用符合 namespace 的 handler
  • 根据 namespace 可以 remove 掉该 namespace 的所有 handler

    1
    $(document).off("click.bs.modal.data-api");

    这样就移除了所有 data-toggle=modal 的效果,但是其他组件,如 tooltip 还可以使用

namespace 分析

前面看的时候发现 jq 对 namespace 进行了 sort,想不明白…
其实 namespace 是很宽松的,局部匹配即可,先后顺序也没有关系.

拿前面的 click.bs.modal.data-api 演示

  1. 绑定事件

    1
    2
    3
    $(document).on("click.bs.modal.data-api", function() {
    console.log(arguments);
    });
  2. 构造 \$.Event 对象 trigger

    1
    2
    var e = $.Event("click.bs.modal.data-api");
    $(document).trigger(e);
  3. \$.Event 实例的 namespace,namespace_re 属性是在 trigger 过程中构建的,下面可以看看这些属性

    1
    2
    e.namespace; // "bs.data-api.modal"
    e.namespace_re; // /(^|\.)bs\.(?:.*\.|)data-api\.(?:.*\.|)modal(\.|$)/

    可以看到

    • namespace 就是 [bs,modal,data-api] sort 后的
    • namespace_re 则是

      1
      new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.\*\\.|)") + "(\\.|\$)" )

      因此 click.data-api , click.bs , click.bs.data-api 都能触发.
      `

看完怎么感觉 namespace 按 startWith 匹配更好呢 !