YUI事件体系之Y.CustomEvent
Contents

上一篇文章中,简要介绍了YUI实现AOP的Y.Do对象。
接下来,我们继续对YUI事件体系进行探索。本次要介绍的是Y.CustomEvent对象,从命名上就可以看出,这个对象在整个YUI事件体系中十分重要。它建立起整个自定义事件的体系,而且,DOM事件也构建在这个体系之上。
Y.Subscriber
Y.Subscriber的作用比较简单:执行回调函数。
1 | Y.Subscriber = function (fn, context) { |
Y.CustomEvent
Y.CustomEvent主要作用是:建立自定义事件机制,为方便的进行事件创建、监听、触发提供良好基础。自定义事件机制,实际上是Observer Pattern(Publish–subscribe Pattern的演化)的一种实现,这种机制能够方便的实现模块间解耦,增强模块的扩展性。
YUI的自定义事件较其它一些js库来说要强大一些,有这样一些好的features:
- 支持事件接口(Event Facade),在回调函数中可以进行调用
- 支持设置默认执行方法
- 支持停止/立即停止传播,并可设定停止传播时执行的方法
- 支持阻止默认行为(默认执行方法),并可设定阻止默认行为时执行的方法
- 支持冒泡。指定冒泡目标序列,就可以顺序的触发事件(需要
Y.EventTarget) - 支持广播。每个自定义事件,都可以设置在当前YUI实例范围内和全局YUI内进行广播
可以看出,YUI的自定义事件和DOM事件极其类似,这种设计自然到我们在用自定义事件时,丝毫感觉不到和DOM事件的差异。
示例
让我们先来看个简单的例子:
1 | // 例1 简单自定义事件 |
有些事件只需触发一次,比如你的各种第一次~~~。来看这个例子:
1 | // 例2 仅触发一次的自定义事件 |
也许你还在琢磨,事件广播是什么?因为YUI使用了sandbox设计,可以生成不同实例绑定不同api,所以才有了事件广播机制。来看这个例子:
1 | // 例3 事件广播 |
文章之前介绍过YUI自定义事件的种种NB之处,那么用起来如何呢,来看下面的例子:
1 | // 例4 复杂自定义事件 |
不要失望,现在还没有介绍到事件体系的精华部分Y.EventTarget,所以很多特性(例如冒泡)还不能体现出来,拭目以待吧。
源代码分析
接下来,让我们看看YUI的内部实现吧。
注:为了更容易的看懂代码的核心,我做了适当的简化,感兴趣的朋友可以去看未删节的源码。
1 | var AFTER = 'after', |
适用场景
自定义事件的适用场景与Publish–subscribe Pattern基本一致。具体来讲,我觉得以下一些场景是非常适合用自定义事件的:
a) 需要暴露接口/行为以满足扩展需要
底层模块一般会设计的尽量简单,解决核心问题,并适当的开放一些接口,方便应用层进行扩展以满足实际需求。例如表单验证控件,有可能需要在某个表单项验证成功/失败后执行一些额外操作,举一个实际的例子:当用户输入的邮箱地址验证成功时,我们会检查是不是某些比较烂的邮件服务商,如果是则给出一些建议。
YUI作为一个底层基础库,在组件/控件层面加入了大量的自定义事件,以满足实际应用中的需要。例如Y.Anim的start、end事件,Y.io的success、failure、end事件,Y.Attribute中的属性变化事件等。
b) 行为可能会被其它模块/方法中止
这一点非常像DOM事件,我们经常会中止一些事件的默认行为,例如anchor的点击事件。
自定义事件 VS 回调函数
这是一个比较难的问题,我自己的看法是:相对回调函数,自定义事件是一种更重但更灵活的方案。在实际应用中,如果对于关心某消息的受众不够清楚,那么就使用事件。否则,比较适合使用回调函数。
MSDN上的解释更好一些:“An event is like an anonymous broadcast, while a call-back is like a handshake. The corollary of this is that a component that raises events knows nothing about its clients, while a component that makes call-backs knows a great deal”。
另外,如果对于性能特别关心,在可能的情况下,尽量使用回调。
参考
Author: Chun Shang
Link: https://springuper.github.io/event-custom/
License: 知识共享署名-非商业性使用 4.0 国际许可协议