YUI事件体系之Y.delegate

在介绍了YUI自定义事件体系和对DOM事件的封装后,本篇文章重点阐述事件方面的一种常用技术——事件代理。事件代理(Event Delegation,又称事件委托)充分运用事件传播模型,用一种十分优雅的方式实现了批量节点事件监听。具体的原理和优点请移步zakas比较古老的一篇文章Event delegation in JavaScript。事件代理在YUI中的实现为Y.delegate。
基本用法
为方便讨论,约定以下名称:
- 代理节点:实际监听事件的节点。在事件传播到此节点时判断是否符合代理条件,符合则执行回调函数。
- 被代理节点:希望监听事件的节点。如果不采用事件代理,那么应该直接监听这些节点的事件。
- 目标节点:事件发生的目标节点,即
event.target。
三者的层次关系从内到外依次为:目标节点 <= 被代理节点 <= 代理节点。
假设html为:
1 | <ul> |
先来看下Y.delegate的简单用法:
1 | // 例1 |
可以看出,回调函数中的this指向的是使用Y.Node包装的被代理节点。
YUI3新加入的Y.Node对象也封装了delegate,例1更常见的实现如下:
1 | // 例2 |
筛选条件除了例1中使用的selector外,还支持函数:
1 | // 例3 |
源码分析
接下来,让我们看看YUI的内部实现吧。
注:为了更容易的看懂代码的核心,我做了适当的简化,感兴趣的朋友可以去看未删节的源码。
1 | var toArray = Y.Array, |
进阶用法
批量代理
Y.delegate支持同时代理多种类型的事件,调用方式有如下两种:
- Y.delegate({ typeA: fnA, typeB: fnB }, el, filter)
- Y.delegate([typeA, typeB], fn, el, filter)
1 | // 例4 |
修改回调函数this,传递数据
1 | // 例5 |
focus、blur事件的代理
在DOM规范中,诸如focus、blur、load、unload、resize等事件是不冒泡的,因为这类事件只限定在某个节点上触发。但focus和blur事件有些特殊,在表单交互方面十分常用,如果能够支持冒泡,那么通过事件代理可以减少很多监听事件的操作。滑稽的是,focusin、focusout两个类似的事件却支持冒泡。
令人欣喜的是,YUI通过定义新的DOM事件实现了focus、blur事件的代理,awesome!
1 | // 例6 |
示例代码
所有示例代码均在GitHub。
参考
Author: Chun Shang
Link: https://springuper.github.io/event-delegate/
License: 知识共享署名-非商业性使用 4.0 国际许可协议