[转]AS3事件处理机制

先来看个例子:
地点:饭馆类(extend Sprite or UIcomponent...,是个容器就行)
人物:客人类(extend EventDispatcher,会说话就行)、厨师类(extend Object,能

满足客人需求就行)

一、四个步骤:注册侦听、分发事件、侦听事件、移除侦听。
(1)、注册侦听:客人进入饭馆,使用addEventListener指定某厨师准备做菜。
(2)、分发事件:客人使用dispatchEvent对厨师进行喊话,表示我要吃什么。喊话内

容被放在Event类或其子类里,主要包括类型、目标和数据三部分。类型(Type)就是点

菜,而不是结账,上酒水。目标(Target)用来记录是哪桌的客人。数据(Data)用来保

存重要信息,如果是点菜,那记的就是菜名。
(3)、侦听事件:根据注册侦听中的需求,厨师开始做菜。
(4)、移除侦听:不移除的后果就是,以后在任意餐馆里喊话叫菜,所有注册过侦听的

餐馆厨师都开始做菜。
一些细节:
(1)、为了方便客人类在饭馆类中使用MXML标签注册侦听,常常在客人类中使用Event

标签。比如[Event(name="onChange", type="components.MyEventTest")]
(2)、注册侦听时,可以使用弱引用,即更改addEventListener中的useWeakReference

属性的默认值false为true。这样垃圾回收器会检测弱引用侦听并自动移除,极其不建

议这样做,而是直接移除侦听。
(3)、当客人类已经继承了某类,无法再继承EventDispatcher时,可以考虑实现

IEventDispatcher接口。额外地,需要实现此接口定义的五个方法addEventListener

、dispatchEvent、willTrigger、removeEventListener和hasEventListener。当然,

在实现过程中,可以灵活地添加别的新特性。

二、事件流机制
(1)、捕获阶段:Flash Player会按照显示列表,从根容器舞台往下找,直到确定是哪

个桌的客人在喊话要菜。
(2)、目标阶段:捕获阶段结束时停在哪个目标对象上。
(3)、冒泡阶段:事件对象从目标对象再次沿显示列表往上移动至根容器舞台,遇到注

册侦听的节点就调用侦听函数。如果想中途中断冒泡,可以使用stopPropagation,详

见文末Event备注部分。
一些细节:
(1)、这三个阶段由Event中的eventPhase属性来记录,1表示捕获,2表示目标,3表示

冒泡。
(2)、目标阶段确定的目标对象由Event中的target属性来记录,冒泡阶段移动的游标

则由currentTarget来记录。事件对象每往上移动一级,就会克隆出一个仅与前副本

currentTarget不同的新副本。这也提示我们,在自定义Event类时,如果打开了冒泡

属性bubbles,则必须要覆盖原有的clone方法,否则在冒泡时就会丢失自定义的存储

数据。同样,最好也覆盖原有的toString方法。
(3)、侦听器的调用一般发生在冒泡阶段。但是当target等于currentTarget,也就是

当前侦听对象就是事件发生对象时,冒泡阶段就没有了,这时目标阶段就发生了侦听

器调用。如果希望在捕获阶段侦听事件,将addEventListener中的useCapture参数改

为true即可,这时冒泡阶段将不再发生侦听。如果希望仍在冒泡阶段继续侦听,需要

新添加一个useCapture为默认值false的侦听。
(4)、事件对象是否可以冒泡要看两点:第一,事件本身是否支持冒泡,由bubbles属

性设定,为true则支持,默认为false;第二,如果事件发生的对象不在显示列表中,

也不可能冒泡,此时只有目标阶段,如Timer和URLLoader。
(5)、显示列表下,某个容器中有两个并列子节点1和2。如果子节点1发出事件,需要

在子节点2中进行侦听,默认情况下是做不到的。常用的一种办法是向子节点1和子节

点2都传入一个相同的对象的实例,在子节点1中用这个对象实例发出事件,在子节点2

中用这个对象实例监听事件(在目标阶段捕获事件)。这样就可以收到字节点1的事件

了。

三、Event备注
属性:
bubbles:只读,布尔,事件是否开启冒泡功能 
cancelable:只读,布尔,处理事件的默认行为是否可以停止。主要针对一些系统事

件,如果值为true,则Event的preventDefault方法可以使用,否则不可用。 
currentTarget:只读,对象,当前正在调用监听器的对象 
eventPhase:只读,整数,返回事件流正经历的阶段。1:捕获,2:目标,3:冒泡 
target:只读,派发事件的目标对象 
type:只读,字符,事件类型。比如鼠标点击事件的类型:click,并被定义为常量:

MouseEvent.CLICK

构造函数:
Event(
  type:String,    事件类型
  bubbles:Boolean = false,   是否冒泡
  cancelable:Boolean = false  是否可以停止
)

方法:
isDefaultPrevented:判断preventDefault 是否已经被调用
preventDefault:停止事件的默认行为。针对一些系统事件,cancelable为true时才

可用。 
stopImmediatePropagation:停止当前的事件流传播,包括当前正在处理的对象 
stopPropagation:停止当前的事件流传播,但不会停止当前正在处理的对象

四、侦听器备注

addEventListener(
  type:String,    事件的类型
  listener:Function,    监听函数
  useCapture:Boolean = false,    是否打开捕获功能 
  priority:int = 0,    监听器优先级别
  useWeakReference:Boolean = false    是否使用弱引用
)

默认情况下,Flex会按照监听器注册的顺序来调用监听函数。使用addEventListener

函数的priority 来实现 监听函数的优先级。priority 为整数类型,数字越大,级别

越高。级别最高的最先被调用。已经存在的监听器,无法被修改优先级。使用MXML添

加的事件监听函数无法指定优先级别,将采用默认的级别。给一个对象注册多个监听

器,即使每个监听器的优先级别不同,但也无法保证后一个执行时前面的监听函数已

经执行完毕。设计时,后面的函数不应该以前者执行完毕为条件。

 

你可能感兴趣的:(事件,Flex,原理,机制,as3)