FLEX 事件机制

今天要写自定义控件与自定义事件,好好的学习了几篇文章,现在总结一下,以便给自己留个提醒:

1flex事件机制:找了个解释的比较好的,转载如下:

事件的传递分为三个阶段,如图:捕获阶段(Capture Phase)、目标阶段、冒泡阶段,比如当你点击了一下Child1 Node时,事件会从Stage->ParentNode->Child1 Node一路传过来(捕获阶段),传到Child1Node时,执行Child1 Node的相应事件函数(目标阶段),然后传回Stage(冒泡阶段):

捕获阶段:事件从目标所在DOM树的根节点依次往下层传递,一直到目标节点之前的过程。在这个过程中,事件将会被从根节点到事件目标之前的所有父节点对象所捕获。如果事件在被注册时设置了useCapture属性为true,那么它会被这期间的所有注册了该事件的父元素对象依次派发。

目标阶段:事件到达目标元素。目标元素如果注册了该事件并且设置了useCapture属性为false,则目标会派发该事件。

冒泡阶段:事件到达目标元素后会接着通过DOM节点向上层父节点冒泡,并最终回到目标所在DOM树的根节点的过程。在这个过程中如果事件是可冒泡事件(最典型的例子就是click事件)并且在被注册时设置了useCapture属性为false,那么它会被这期间的所有注册了该事件的父元素对象派发。

2,举个简单而常见的例子:

canvas上有n个button,如果给每个button注册一个click事件,那么内存中就需要维护n个listener。由于click事件是可冒泡事件,那么更好的解决办法就是给canvas注册一个click事件,即

canvas.addEventListener(MouseEvent.CLICK, onMouseClickHandler);

调通过事件的冒泡阶段由n个button共同的父元素canvas来派发click事件,并且可以通过事件参数的target属性来决定调用哪个button对应的处理函数。这样做的的好处就可以只注册一个事件监听从而代替为n个button注册n个事件。

3.target和currentTarget究竟谁是事件的派发者?

target:事件指向的目标,但并非事件的派发者。 在一个事件整个生命周期中所有被派发的事件处理函数内部的target对象是一样的,每个被监听者派发的事件处理函数中的target一定都是同一个对象。
currentTarget:事件的派发者。调用注册在事件上的回调函数的那个对象,简单的说就是派发事件的对象。

4.useCapture到底有何用?

首先看看AS3中为IEventDispatcher类型对象注册事件监听的接口(完全符合W3C标准)

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

最显而易见的用处,如果没有这个参数,那么走完事件的生命周期,所有目标父节点上注册的事件都会被执行两次(捕获阶段一次+冒泡阶段一次)!也正因为有useCapture这个参数,整个事件机制的运作才有了分支,或者更说是被分成两个独立部分。

拿上面“n个button的例子”来说,如果用户点击某一个button将会触发click事件,首先我们来看下整个click事件的生命周期中将会经历的UI对象:

stage → canvas → button →  canvas → stage

然后我们再看分析一下事件流的三个阶段。
首先是捕获阶段:
事件从该button所处显示对象树的根出发,也就是stage,stage上未注册click事件,不会做出任何响应。
然后来到stage的子节点即canvas,注意我们在canvas上注册了click事件,而此时click事件不会被派发,因为例子中我们注册的click事件使用的是默认的useCapture=false参数,即click事件必须在目标和冒泡阶段才能被派发。
然后进入目标阶段:
尽管目标是button,但由于其并未注册任何click事件监听所以也不作出任何响应。
由于click事件是可冒泡事件,所以最后会进入冒泡阶段:
从button到canvas,canvas上注册了click事件监听,所以canvas派发该事件,进入事件处理函数,此时target是button,currentTarget是canvas。

如果useCapture=true呢?
还是“n个button的例子”,我们给canvas注册一个useCapture=true的click事件会怎么样呢即

canvas.addEventListener(MouseEvent.CLICK, onMouseClickHandler, true );

这样有三点好处:

1. 事件不会经历目标和捕获阶段,这样只有当且仅当事件的target为监听对象的子对象时,事件才会被派发。“n个button的例子”当监听器的参数useCapture=true,用户点击目标如果是canvas自己,则事件不会被派发。换言之只有点击canvas上的子对象,比如某个button或是canvas上的其他UIcomponent,click事件才会触发。再解释一遍为什么吧。点击canvas本身,事件流首先进入捕获阶段从目标(canvas)所在显示对象列表的根stage开始向下,来到canvas上,这时因为event.target==canvas,进入目标阶段,尽管canvas注册了click事件,但useCapture参数是true,那就是说事件只能在捕获阶段被派发,所以这个事件并不会被派发出来,也就是点击canvas没有任何响应。
想象一下应用场景,比如那种点击小球会得分的游戏,我们可以给小球的容器对象加上监听,但又不想在事件处理函数中接判断用户是否点到了容器本身上,这时我们大可放心的给容器对象加上useCapture=true的点击事件监听,让事件在捕获阶段就派发出来,这样就再也不用在函数中check来check去了,管它event.target是谁呢。
2. 不用考虑事件是否支持冒泡。
3. 由于少了两个阶段,必然少折腾一些传递。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值