flex 事件之理解

来源:互联网 发布:监听端口 编辑:程序博客网 时间:2024/06/15 15:51

       首先,申明本文是转载http://blog.csdn.net/ivanmarkliu/archive/2009/07/08/4327570.aspx,大家可以访问该链接,也可以直接阅读本文后续部分以了解flex事件。接下来简单谈下为何要转载此文及本人对此文的一些补充。

       可以这样说flex是事件驱动的,熟练掌握事件对于提高flex开发水平是至关重要的,flex的经典绑定机制就是基于event。网上对于flex event的介绍很多,其中不乏官方的e文,但是本人觉得本转载之文对于事件的核心“事件传播”讲解的是比较通俗易懂的,且有demo,只要运行demo即能理解大概。因此本人认为结合此转载篇,再了解下事件派发的一个借口IEventDispatcher和基类EventDispatcher,再熟悉下自定义event便可熟练掌握flex event了。

    在转载正文之前,先补充事件传播的3个阶段值,使大家更易理解。

    EventPhase.CAPTURING_PHASE: 1 捕获阶段

EventPhase.AT_TARGET: 2,目标阶段

EventPhase.BUBBLING_PHASE: 3,冒泡阶段

 

 

///////////////////////////////////////////////转载正文/////////////////////////////////////////////////

1. 最简单的事件

以下代码:

   
1:


xml

version
="1.0"
encoding
="utf-8"?>

   
2:


<
mx:Application

xmlns:mx
="http://www.adobe.com/2006/mxml"

   
3:

                

layout
="absolute">

   
4:

    

<
mx:Script
>

   
5:

        

[CDATA[

   
6:

            
import flash.events.MouseEvent;

   
7:

            
import mx.controls.Alert;

   
8:

 
   
9:

            
private function btnClick(event:MouseEvent):void {

  
10:

                
Alert.show("Hello Event");

  
11:

            
}

  
12:

        
]]

>

  
13:

    

mx:Script
>

  
14:

    

<
mx:Button

x
="311.5"

  
15:

               

y
="215"

  
16:

               

label
="Button"

  
17:

               

click
="btnClick(event)"/>

  
18:


mx:Application
>

效果很简单,当单击鼠标时弹出一个提示窗口,内容“HelloEvent”。代码中,buttonclick设定了事件触发的时候执行btnClick方法中的代码。

其中,event对象就是这个组件分发的事件对象,即type “click”MouseEvent的一个实例。这个event对象包含了触发该事件时的各种信息,比如触发事件对象是哪个,监听对象是哪个,触发时鼠 标点在哪里等等,不同的event类会包含不同的属性,比如KeyboardEvent包含了键盘点击了哪个键。

下面将会解释到,这个事件会在事件流的target阶段被触发。

2. 事件的传播

在官方的帮助手册里有提到,当事件触发之后,FLEX3个检测事件监听 器的阶段, 3个阶段的发生的顺序如下:

1. 捕获
2.
目标
3.
上浮

在任意一个阶段, 节点们都有机会操作事件。

关于这三个阶段的描述,发现很多网上的版本说不清楚。帮助手册里原文是这 样的:

l The first part of the event flow iscalled the capturing phase. This phase comprises all of the nodes from the rootnode to the parent of the target node. During this phase, Flash Player examineseach node, starting with the root, to see if it has a listener registered tohandle the event. If it does, Flash Player sets the appropriate values of theEvent object and then calls that listener. Flash Player stops after it reachesthe target node's parent and calls any listeners registered on the parent.

l The second part of the event flow,the targeting phase, consists solely of the target node. Flash Player sets theappropriate values on the Event object, checks the target node for registeredevent listeners, and then calls those listeners. For more information.

l The third part of the event flow, thebubbling phase, comprises all of the nodes from the target node's parent to theroot node. Starting with the target node's parent, Flash Player sets theappropriate values on the Event object and then calls event listeners on eachof these nodes. Flash Player stops after calling any listeners on the rootnode.

总结了一下,如下解释:

l 捕获阶段(capture)
在这个阶段,Flash Player会去查找事件的触发源,它是通过根显示元素(root display object)逐层向下寻踪,直到找到事件的发起源头的父节点,如你在buttonclick后,FlashPlayer找到的事该button对象。在这个阶段监视器(listener)默认是不会收到任何消息的(默认只在targetbubble阶段收到消息)

l 目标执行阶段(target)
这个阶段会调用事件发起者中的事件监听器。

l 冒泡阶段(bubble)
最后的这个阶段其实就是第一个阶段的逆向过程。它就是在事件代码执行完毕后,从事件发起源头的父节点,通过子元素逐级向父元素发出该事件,一直到根元素。过程中,在节点处添加的listener会收到消息并且触发。前提是事件支持bubble阶段。

设置listener的方法为使用下面的function

   
1:

addEventListener(type:String, listener:Function,useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false)

l type:Event的类型,例 如click事件type就是click等。

l Listener:响应事件的方 法,即当捕获到事件时你要程序做什么。

l useCapture:默认为 false。当设置为true时,事件会在捕获阶段就触发;设置为false时,事件则在冒泡阶段触发。因为默认是false,所以之前提到在捕获阶段,listener默认是不会收到任何消息的。如果想让事件既在捕获阶段触发又在上浮阶段触发,可以用两次addEventListener,一次把这 个参数设成false,一次设成true,分别在这两个阶段触发。

l priority:优先级。

l useWeakReference: 是否设置为弱引用。如果被设置为true,则表示告诉Flash Player,当直接引用这个监听器的对象数量为0时,就可以马上回收它。默认是false的话,还需要遍历这个引用可以到达的其它引用,确保不会发生循 环引用时才回收资源。

拿本文第一章中的例子改造一下说明这三个阶段以及addEventListener的使用:

   
1:


xml

version
="1.0"
encoding
="utf-8"?>

   
2:


<
mx:Application

xmlns:mx
="http://www.adobe.com/2006/mxml"

   
3:

                

layout
="absolute"

   
4:

                

creationComplete
="creationComplete()">

   
5:

    

<
mx:Script
>

   
6:

        

[CDATA[

   
7:

            
import flash.events.MouseEvent;

   
8:

            
import mx.controls.Alert;

   
9:

 
  
10:

            
private function btnClick(event:MouseEvent):void {

  
11:

                
trace(event.eventPhase + ":Button:" + event.currentTarget.id + ":" + event.target.id);

  
12:

            
}

  
13:

 
  
14:

            
private function btnClick2(event:MouseEvent):void {

  
15:

                
trace(event.eventPhase + ":Application:" + event.currentTarget.id + ":" + event.target.id);

  
16:

            
}

  
17:

 
  
18:

            
private function btnClick3(event:MouseEvent):void {

  
19:

                
trace(event.eventPhase + ":VBox:" + event.currentTarget.id + ":" + event.target.id);

  
20:

       
     
}

  
21:

 
  
22:

            
private function btnClick4(event:MouseEvent):void {

  
23:

                
trace(event.eventPhase + ":AddButton:" + event.currentTarget.id + ":" + event.target.id);

  
24:

            
}

  
25:

 
  
26:

            
private function creationComplete():void {

  
27:

                
addEventListener(MouseEvent.CLICK, btnClick2, false);

  
28:

                
addEventListener(MouseEvent.CLICK, btnClick2, true);

  
29:

                
vb.addEventListener(MouseEvent.CLICK, btnClick3);

  
30:

                
tb.addEventListener(MouseEvent.CLICK, btnClick4);

  
31:

            
}

  
32:

        
]]

>

  
33:

    

mx:Script
>

  
34:

    

<
mx:VBox

x
="200"

  
35:

             

y
="147"

  
36:

             

id
="vb"

  
37:

             

height
="100%">

  
38:

       
 

<
mx:Button

id
="tb"

  
39:

                   

label
="Button"

  
40:

                   

click
="btnClick(event)"/>

  
41:

    

mx:VBox
>

  
42:


mx:Application
>

为了解释事件的三个阶段,我把button再放到一个vbox里面。在 Application加入两个listeneruserCapture分别设置为falsetrue,这样就可以在Application捕获到捕获阶段和上浮阶段的事件。然后在VBox设置一个listeneruserCapture属性使用默认的false,用于证明上浮阶段的顺序。再在 Button上设置一个listener,证明Button上的listener没有参与捕获阶段和上浮阶段。

代码中用于检测事件阶段的EventeventPhase属性。这个属 性分别用123表示Capture PhaseTarget PhaseBubble Phase

还有就是eventcurrentTargettarget属性。因 为在事件流的过程中,event对象会被动态的在各个层次节点传递。currentTarget就是当前的节点对象,target则是事件分配源对象,这 个例子里面target就是button

Debug跑一下以上代码,然后点击Button,控制台输出如下:

   
1:

1:Application:HelloEvent:tb
   
2:

2:Button:tb:tb
   
3:

2:AddButton:tb:tb
   
4:

3:VBox:vb:tb
   
5:

3:Application:HelloEvent:tb

结果中可以看到上浮的过程是由内而外的,以及可以看到事件发出对象的监听 只在target阶段被执行。

在事件的传播过程中,任何阶段中都可以使用以下两个函数停止事件传播:

   
1:

stopPropagation()
   
2:

stopImmediatePropagation()

这两个函数的共同特征就是,可以阻止事件继续传播到别的节点,而且都不影 响对象和事件的关联关系。不同的地方是,stopPropagation() 要等到当前节点所有事件都完成了以后才生效,而stopImmediatePropagation()会马上生效。

3. 事件的分派

最终继承自EventDispatcher的对象都会含有 dispatchEvent这个方法,他有一个参数,事件对象。事实上所有的事件都是通过这个函数分派出去的. dispathEvent(Event),我们当然也可以自己定义这个Event,然后用第二章中的各种方式去捕获自定义的Event,这个呆会会说到。

先看下面的代码:

   
1:


xml

version
="1.0"
encoding
="utf-8"?>

   
2:


<
mx:Application

xmlns:mx
="http://www.adobe.com/2006/mxml"

   
3:

                

layout
="absolute"

   
4:

                

creationComplete
="creationComplete()">

   
5:

    

<
mx:Script
>

   
6:

        

[CDATA[

   
7:

            
import flash.events.MouseEvent;

   
8:

            
import mx.controls.Alert;

   
9:

            
private function btnClick(event:MouseEvent):void {

  
10:

                
trace("Click:Button:" + event.currentTarget.id + ":" + event.target.id + ":" + event.eventPhase);

  
11:

                
tb.dispatchEvent(new MouseEvent(flash.events.MouseEvent.DOUBLE_CLICK, true));

  
12:

            
}

  
13:

            
private function btnDoubleClick(event:MouseEvent):void {

  
14:

                
trace("DoubleClick:Button:" + event.currentTarget.id + ":" + event.target.id + ":" + event.eventPhase);

  
15:

            
}

  
16:

            
private function doubleClickHandler(event:MouseEvent):void {

  
17:

                
trace("Application:doubleClick");

  
18:

            
}

  
19:

            
private function creationComplete():void {

  
20:

                
addEventListener(flash.events.MouseEvent.DOUBLE_CLICK, doubleClickHandler);

  
21:

            
}

  
22:

        
]]

>

  
23:

    

mx:Script
>

  
24:

    

<
mx:Button

x
="311"

  
25:

               

y
="180"

  
26:

               

id
="tb"

  
27:

               

label
="Button"

  
28:

               

click
="btnClick(event)"

  
29:

               

doubleClick
="btnDoubleClick(event)"/>

  
30:


mx:Application
>

上面的程序,现在Application添加一个鼠标双击事件的监听,在 Button注册一个click事件。在click响应的函数里面使用dispatchEvent,将一个鼠标双击事件由Button发出。控制台结果如下:

   
1:

Click:Button:tb:tb:2
   
2:

DoubleClick:Button:tb:tb:2
   
3:

Application:doubleClick

可以看到,单击这个Button的时候Application捕获到了双 击事件。使用这个函数,我们就可以在自定义的控件中分派自定义的事件了。

 

 

原创粉丝点击