山寨版AS3事件冒泡机制的实现
AS3实现了事件传递,分成三段Capture,target和bubble,其中bubble就是向树根传递。这个机制非常之经典和好用,可惜它只存在在基于DisplayObject的对象树中,其它时候只能把事件老老实实的从一个对象直接传递到另一个对象。
这次我来玩个有趣的。仿造AS3内置的机制来制作一个更加通用的冒泡框架,相信可以用很多用处(至少已经用在我的项目上了)。自己实现事件传递,让它支持任何事件任何数据结构(无论队列,还是树),甚至可以传递任何对象(而不仅限于事件对象)。其实bubble的过程不难,就是把一个对象(特例就是事件对象)在一个链表里自动传递,不断的向上抛,过程跟AS3的事件机制别无二致。为了能扩展,我准备了接口和初步的实现类:IBubbleDispatcher和CBubbleDispatcher。跟IEventDIspatcher和EventDispatcher一样吧。来看看代码。
package org.gl.geom.abstract { import flash.events.Event; /** * ... * @author Jonson */ public interface IBubbleDispatcher { /** * add to bubble tree * * @param child * @param father */ function registerAsMyChild(child:IBubbleDispatcher):void; /** * dispatch event, then bubble * * @param event */ function bubble(event:Event):void; /** * it's better to be override in subclass * * @param event * @return true means continue bubble */ function myBubbleEventHandler(event:Event):Boolean } }
package org.gl.geom.abstract { import flash.events.Event; /** * ... * @author Jonson */ public class BubbleDispatcher implements IBubbleDispatcher { ////////////////////////////////////////////////// // render event bubble private var __my_parent__:IBubbleDispatcher; /** * add to bubble tree * * @param child * @param father */ public function registerAsMyChild(child:IBubbleDispatcher):void { if (child is BubbleDispatcher) { (child as BubbleDispatcher).__my_parent__ = this; } } /** * dispatch event, then bubble * * @param event */ public function bubble(event:Event):void { if (__my_parent__) { var neve:Event = event.clone(); if (__my_parent__.myBubbleEventHandler(neve)) { __my_parent__.bubble(neve); } } } /** * it's better to be override in subclass * * @param event * @return true means continue bubble */ public function myBubbleEventHandler(event:Event):Boolean { //it's better to be override in subclass return true; } } }
为了便于理解,我这里与AS3内置的EventDispatcher做些比较。
- 把CBubbleDispatcher做父类(和EventDispatcher一样)。
- 使用registerAsMyChild注册叶子对象(类似于addChild和addEventListener的组合,先把叶子对象作为当前对象的child,然后注册监听),这样的话,叶子抛出的事件对象就能被父亲对象处理了,或者再向上抛。
- 使用bubble发出事件(相当于dispatchEvent)。
- 子类重写myBubbleEventHandler来处理事件,返回true说明继续向上传递(类似于stopPropagation功能),如果不需要处理就不必重写。这样设计的好处是,不需要根据不同的Event type而写上很多很多的addEventListener。
补个小例子
class parent1Class extends CBubbleDispatcher { public function parent1Class(){this.registerAsMyChild(_child);} private var _child:parent2Class = new parent2Class(); } class parent2Class extends CBubbleDispatcher { public function parent2Class(){this.registerAsMyChild(_child);} private var _child:childClass = new childClass(); } class childClass extends CBubbleDispatcher { public function try():void{this.bubble(new Event("UP"))}; }


呵呵,山寨的和原创就是不一样,有创意,不过还是有些不足
to Vniu
有哪些不足呢,指教下
如果继承于CBubbleDispatcher,便不能继承其它;而自实现IBubbleDispathcer接口又嫌麻烦,能否设计出一个Manager,或者别的,可以方便的使用。
此或为vniu所言不好之处。
to sban
其实我的初衷是让最基类继承CBubbleDispatcher,这样就不会干扰你的继承体系了