as3:事件机制原理

来源:互联网 发布:金蝶初始数据如何录入 编辑:程序博客网 时间:2024/05/01 01:10
addEventListener()方法
public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void

 

 

 

 

 

 type:String — 事件的类型。   listener:Function — 处理事件的侦听器函数。此函数必须接受 Event 对象作为其唯一的参数,并且不能返回任何结果,如下面的示例所示:

function(evt:Event):void

函数可以有任何名称。

  useCapture:Boolean (default = false) — 确定侦听器是运行于捕获阶段、目标阶段还是冒泡阶段。如果将 useCapture 设置为 true,则侦听器只在捕获阶段处理事件,而不在目标或冒泡阶段处理事件。如果 useCapturefalse,则侦听器只在目标或冒泡阶段处理事件。要在所有三个阶段都侦听事件,请调用 addEventListener 两次:一次将 useCapture 设置为 true,一次将 useCapture 设置为 false.   priority:int (default = 0) — 事件侦听器的优先级。优先级由一个带符号的 32 位整数指定。数字越大,优先级越高。优先级为 n 的所有侦听器会在优先级为 n -1 的侦听器之前得到处理。如果两个或更多个侦听器共享相同的优先级,则按照它们的添加顺序进行处理。默认优先级为 0。   useWeakReference:Boolean (default = false) — 确定对侦听器的引用是强引用,还是弱引用。强引用(默认值)可防止您的侦听器被当作垃圾回收。弱引用则没有此作用。

类级别成员函数不属于垃圾回收的对象,因此可以对类级别成员函数将 useWeakReference 设置为 true 而不会使它们受垃圾回收的影响。如果对作为嵌套内部函数的侦听器将 useWeakReference 设置为 true,则该函数将作为垃圾回收并且不再是永久函数。如果创建对该内部函数的引用(将该函数保存到另一个变量中),则该函数将不作为垃圾回收并仍将保持永久。

 

我们先看第四个参数,就是priority。。这个优先级应该是很好理解了,就是优先级高的先执行,低的后执行,数字大的为高,小的为低。默认的都是0。也就是说按定义先后执行。比如:

A.addEventListener(MouseEvent.CLICK,onClick1);

A.addEventListener(MouseEvent.CLICK,onClick2);

那么默认的,在点A的时候就会是onClick1执行,onClick2执行。这样的顺序。

如果是:

A.addEventListener(MouseEvent.CLICK,onClick1,false,1);

A.addEventListener(MouseEvent.CLICK,onClick2,false,0);

这样的话,在点A的时候就会是onClick2执行,onClick1执行。这样的顺序。

然后再看第三个参数:useCapture

从定义可以看出,这个参数是一个Boolean类型,就是true OR false。而且默认不写的话是false.

他主要是控制我们的侦听是发生在捕获阶段、目标阶段和冒泡阶段中的哪个阶段的。是不是有点懵。没关系,下面我们先讲讲这三个阶段。

 

上面是两个图,左边一个是说明一种层次关系,就是舞台上有一个东东,东东里面又有两个小东东。

第二个图是说如果小东东一被点击的话会出现的现像。我们知道addEventListener只是添加一个事件侦听,也就是说你做不做这个工作,只要你点击了元件,事件流是客观存在的。下面我们就第二个图看看这个客观存在是什么样的。

可以看见的有三个箭头,第一个Capture Phase(捕获阶段)第二个Target Phase(目标阶段)第三个Bubbing Phase(冒泡阶段)。

什么意思呢,就是说你点了Child1这个东东。那么事件会从舞台开始,往下到你点的东东,再向上到舞台.明白一点说,就是首先系统会认为你点击了舞台,然后是点击了Parent,然后是点击了你的目标Child1.然后再回上去。其中事件从stage跑到Child1之前,叫做捕获阶段,到达Child1叫做目标阶段(真正点击的目标),再回上去叫做冒泡阶段(很形像吧)。

三个阶段搞清楚了吧。那你是不是对这个Capture,捕获阶段这个单词有点眼熟呢,不错就是第三个参数里面useCapture.(终于又绕回来了)。现在想想,我们为Parent上注册了一个事件,其实就相当于在他上面放了一只耳朵,用来听听事件是不是经过了那里,经过就执行函数,那么三个阶段下来,事件是不是两次都经过了它,那耳朵是不是听到了两次事件。那函数不是要执行两次??这个问题的解决,就是应用useCapture这个参数,这个参数在默认为false表示,事件只能在目标阶段和冒泡阶段被侦听到,假如上图stage 和parent都有监听click事件的话,那就是child1先执行、再parent、最后stage。但是如果为true的话,表示只能在捕获阶段被侦听到,所以stage会先执行、再parent、最后才是目标currentchild1执行。

********************************************************************************

在场景中再一个矩形影片剪辑,实例名mc
双击进入后,再画一个矩形(稍小的),做成影片剪辑,实例名a
这样做成了一个父子套的关系,
然后写代码

 

 

*************************************************************************

stopImmediatePropagation()方法 

public function stopImmediatePropagation():void

 

 

防止对事件流中当前节点中和所有后续节点中的事件侦听器进行处理。此方法会立即生效,并且会影响当前节点中的事件侦听器。相比之下,在当前节点中的所有事件侦听器都完成处理之前,stopPropagation() 方法不会生效。

代码:
mc.a.addEventListener(MouseEvent.CLICK,onFunA)
mc.addEventListener(MouseEvent.CLICK,onFunB)
function onFunA(_evt:MouseEvent){
trace(_evt.currentTarget.name,"_",_evt.target.name)
}
function onFunB(_evt:MouseEvent){
trace(_evt.currentTarget.name,"_",_evt.target.name)
}

运行,在单纯mc的范围上单击,返回的target是mc,currentTarget也是mc
输出结果:
mc _ mc
而如果鼠标再移入一点,在a影片剪辑上单击的时候,
事件流先到达目标阶段,触发a的侦听,然后冒泡阶段,再到mc
所以target一直是a,但currentTarget目标会在两次触发中分别为a(内层)和mc(外层)
输出结果:
a _ a
mc _ a
上面这个实验就是想证明自己的一个想法,冒泡事件是否触发的顺序是从底到顶的,上面的输出证实了这点理解.


总结:
1.事件流是面向DisplayObject的一个过程机制,但凡显示对象触发的事件,必有这个流过程,自上而下,再自下而上
2.事件流机制是在同一条路径上的父子关系的显示对象都会参与的(默认)
3.参与事件流的对象,对内部子对象,同样会触发MOUSE_OUT事件的
4.最重要的一点就是,子对象触发的事件,只要父对象有侦听,那么无论如何,父对象都会触发一次所侦听的事件
而且顺序是子对象先触发事件,然后父对象再触发(这是由冒泡阶段的顺序触发的
)
5.将addEventListener函数中的第三个参数设为true,则只在捕获阶段侦听,对于没有子对象的元素,事件是不会触发的,只有当子对象同样侦听相同事件时,才会触发事件(因为没有目标阶段)