Flex的事件其实很容易明白,象JAVA语言一样,给某个控件注册一个listener,然后事件发生的时候触发相应的函数,这点我相信大多数人都能够明白。今天我想要说的不是这个,而是更加细节的一些东西。
1.事件的传播过程。
Flex事件有下面三个阶段,当事件发生时依次为:
1.capturing(捕捉)
2.targeting(目标)
3.bubbling(起泡或者回溯)
在这些阶段,程序中从根节点到触发事件的节点(这里的节点就是指可以把整个MXML文件看作是一个XML,那么节点就是各个标签)都有机会来响应事件。假 设用户点击了HBox容器中的一个Button,在capturing阶段Flex会检查Application和HBox是否对此事件定义了 listener,然后在targeting阶段Flex触发Button的listener,在bubbling阶段Flex又会检查 Application和HBox,不过这次的顺序和capturing状态时相反。也就是说,事件发生的时候从根节点到目标节点的父节点有两次机会可以 响应事件。
整个事件的这三个阶段也就形成了一个事件流。所以你可以在工作流中的任意节点上注册listener而不用担心不会被触发。还有一点需要说明的是,只有可 视的对象(比如一些容器和控件)才有第一个和第三个阶段,而像Socket这种没有界面的对象只能在targeting时被触发,它无法参与第一个和第三 个阶段。
虽然每个对象都有两次响应事件的机会,但是在默认情况下,capturing状态时没有对象会响应事件,除非你特别声明要在capturing阶段响应。你可以把addEventListener() 中的use_capture参数设置为true,这样就可以在capturing阶段响应了。但是请注意,一旦在capturing中响应过之后在bubbling阶段就不会再响应了。如果你想要让listener在capturing和bubbling阶段都响应的话,只能两次调用addEventListener() ,一次把use_capture参数设置为true,第二次把它设置为false。
另外,你只能为可以触发一个事件的对象注册此事件的listener。比如,你就不能为一个Form定义一个Click事件,即使它包含一个Button控件,因为Form无法触发Click事件。
你可以使用下面两个函数来中止事件的传播:
stopPropagation()
stopImmediatePropagation()
两者唯一的区别就是stopPropagation()是在当前对象的所有listener执行完毕之后再中止事件的传播,而另外一个是立刻终止。
2.Flex事件中的target和currentTarget
每个Event对象都有target和currentTarget属性,他们可以帮助你跟踪事件传播过程。target指的是触发事件的对象,而 currentTarget则是指当前阶段正在被检测到的对象。这样说可能不太好理解,拿上面的那个例子来说吧,在单击事件中target就是那个 button(或者其子组件),不会变,而currentTarget则首先是Application,然后是HBox,然后……明白了吧? currentTarget就是当前正在被事件所检测的对象。currentTarget在Flex 1.5中是没有的,是Flex 2新加入的。
当我点击一个Button时,target很有可能并不是这个Button,而是Button的UITextField,就是显示按钮文字的组件。但是大 多数时候你都是想操作Button对象或者其他注册了listener的对象,很少有人为UITextField对象注册listener。所以大多数时 候你都用currentTarget而不是target来操作他们。举个例子:
程序代码
<mx:Button label="OK" click="trace(event.currentTarget.label)"/>
在这种情况下,currentTarget就是指Button,而target指什么就取决于用户点击了Button上哪个地方了。所以一般你很少用到target属性,大多数情况下都应该使用currentTarget。