当前位置:首页 > 设计在线 > 平面动画 > Flash > AS2再讲事件处理机制(重写 EventDispatcher 类)

AS2再讲事件处理机制(重写 EventDispatcher 类)

点击次数:23 次 发布日期:2008-11-21 23:32:59 作者:源代码网
源代码网推荐

先前在 事件处理机制 一文中.我们讲述了在 AS2 中应用事件处理机制的几种(回调函数,addListener,addEventListener)方法.
和建立自己的强大的事件处理机制(修改 EventDispatcher 类,建立 Event 类.等等).对于前文.本人对某些抱有不足.事因个人.
还请见谅.在前文中遗留的某些不足.有个很重要的不足.那就是作用域.在前文中我们修改了 Delegate 类勉强解决了此不足.但
不灵活.而且增加了额外的,且没必要的负担.本人在此不足上下了不少功夫.最后找到了一个折中的方法.此方法原理同 Delegate
类(将 Delegate 类的功能整合到 EventDispatcher 类中,也就是一种变相的方法,其实还是要执行 Delegate 类的步骤).其余的
不足在本文可以体现出来.具体实现在稍后讲述.本文重点在于重写 EventDispatcher 类.简化了不必要的功能.增加了实用的功
能.使其更加灵活.代码简洁易懂,且易读.

在本教程中你将完成下列内容.
       1.定义 IEventDispatcher 接口.
       2.重写 EventDispatcher 类.
       3.简单的示例.
       4.小结.

[1.定义 IEventDispatcher 接口]
接口可以理解是类的计划书,模板,协议.IEventDispatcher 接口定义用于添加或删除事件侦听器的方法,检查是否已注册特定类型的
事件侦听器,并调度事件.
此接口比较简单(意义不凡).定义了4个方法.参数及具体功能后面讲述.

IEventDispatcher.as 文档详细:
Classes/AS2/events/IEventDispatcher.as

打开 IEventDispatcher.as 文档.输入下面的代码:

 

[Copy to clipboard] [ - ]
CODE:
//----------------------------------------
import AS2.events.Event;
//----------------------------------------
interface AS2.events.IEventDispatcher
{
    //添加事件侦听器.
    public function addEventListener(type:String, listener:Function, scope:Object):Void;
    //移除事件侦听器.
    public function removeEventListener(type:String, listener:Function):Void;
    //调度事件.
    public function dispatchEvent(event:Event):Void;
    //检查是否已注册特定类型的事件侦听器
    public function hasEventListener(type:String):Boolean;
}

保存文档.

[2.重写 EventDispatcher 类]
EventDispatcher 类继承 Object 类,并实现 AS2.events.IEventDispathcer 接口.提供添加或移除事件侦听器的方法,
检查是否已注册特定类型的事件侦听器,并调度事件.
此类的改变:
1.addEventListener 方法增加了一个 scope 参数.此参数用来指定事件的作用域.默认为事件的目标(广播事件对象).
2.增加 hasEventListener 方法.此方法用来检查是否已注册特定类型的事件侦听器.
3.事件侦听器统一为函数.不再是对象.
4.删除了 initialize 方法.此方法没有替换方法.但有解决方法.
5.构造函数中添加了一个 target 参数(AS3 中此参数是 IEventDispatcher 类型,此处为什么不是呢?将此参数改为
IEventDispatcher 类型时.固然体现了 IEventDispatcher 接口的不凡,但当不继承此类时.没有选择的必需实现
IEventDispatcher 接口,对于想添加自己的一些实现固然好.但如果不需要添加自己的一些实现,没有必要的去实现
IEventDispatcher 接口,而此参数不接受其它类型.是件麻烦事.所以此处改为 Object 类型.于是乎 AS3 中为什么
不是 Object 类型呢?本人认为是考虑到 OOP 思想吧.Adobe 毕竟是一个公司).此参数是事件的目标(广播事件对象).
此参数只有在不继承此类时才能使用.继承此类时请勿使用此参数
注意: 此类中一些方法的语法已更改如下:
         addEventListener(事件名, 这里只能是函数, 作用域);
      removeEventListener(事件名, 这里只能是函数);
      dispatchEvent(这里只能是 Event 对象或其子对象);

EventDispatcher.as 文档详细:
Classes/AS2/events/EventDispatcher.as

打开 EventDispatcher.as 文档.输入下面的代码:

 

[Copy to clipboard] [ - ]
CODE:
//----------------------------------------
import AS2.events.Event;
import AS2.events.IEventDispatcher;
//----------------------------------------
class AS2.events.EventDispatcher extends Object implements IEventDispatcher
{
    //----------------------------------------
    //事件的目标(广播事件对象).
    private static var __target:Object;
    //----------------------------------------
    public function EventDispatcher(target:Object)
    {
        EventDispatcher.__target = (target == undefined ? this : target);
    }
    //----------------------------------------
    /**
    * 添加事件侦听器.
    * 参数:
    * type:String          ---事件的类型.
    * listener:Function    ---处理事件的侦听器函数.
    * scope:Object         ---事件的作用域.默认为事件的目标(广播事件对象).
    */
    public function addEventListener(type:String, listener:Function, scope:Object):Void
    {
        if(this[type] == undefined){ this[type] = []; }
        this.removeEventListener(type, listener);
        this[type].scope = (scope == undefined ? EventDispatcher.__target : scope);
        this[type].push(listener);
    }
    //----------------------------------------
    /**
    * 移除事件侦听器.
    * 参数:
    * type:String          ---事件的类型.
    * listener:Function    ---处理事件的侦听器函数.
    */
    public function removeEventListener(type:String, listener:Function):Void
    {
        if (this[type].length > 0) {
            var queue:Array = this[type];
            var len:Number = queue.length;
            for(var i:Number = 0; i < len; i ++){
                if(queue[i] == listener){
                    queue.splice(i, 1);
                    return;
                }
            }
        }
    }
    //----------------------------------------
    /**
    * 调度事件.
    * 参数:
    * event:Event    ---事件对象.包含侦听器可用来处理该事件的有关信息,
    *                   当发生事件时,事件对象将作为参数传递给事件侦听器.
    */
    public function dispatchEvent(event:Event):Void
    {
        if(this[event.type].length > 0){
            event.target = EventDispatcher.__target;
            var queue:Array = this[event.type];
            for(var i:String in queue){
                queue[i].apply(queue.scope, [event]);
            }
        }
    }
    //----------------------------------------
    /**
    * 检查是否为特定事件类型添加了事件侦听器.
    * 参数:
    * type:String    ---事件的类型.
    * 返回:
    * Boolean        ---如果指定 事件的类型(type) 已添加了事件侦听器,则返回 true,否则返回 false.
    */
    public function hasEventListener(type:String):Boolean
    {
        return (this[type].length > 0);
    }
    //----------------------------------------
}
保存文档.

EventDispatcher 类中的方法及其参数的功能在注释中已说明.下面讲述它们具体是怎么工作的:

此类中用来存储事件侦听器的是采用事件名作为标识符的数组.每个事件拥有一个数组.addEventListener 方法
向数组中添加元素(事件侦听器).removeEventListener 方法向数组中移除元素(事件侦听器).dispatchEvent 方
法执行数组中的元素(事件侦听器).hasEventListener 方法检查数组中是否有元素.

整体的工作流程如下:

addEventListener 方法,首先向数组中添加元素(事件侦听器).
                            |
removeEventListener 方法.其次移除数组中重复的元素(事件侦听器)(如果有).在此处此方法在 addEventListener 方法内部被调用.
                            |
dispatchEvent 方法.最后在事件触发时调用此方法来执行数组中的元素(事件侦听器)(如果有).此方法总是在事件触发时调用.


下面讲述它们内部是怎么实现的:
1.addEventListener 方法.此方法在前文中详述过.此处不再赘言.此处只对 scope 参数作解释.

 

[Copy to clipboard] [ - ]
CODE:
    //主要用于获得事件的作用域.默认使用事件的目标(广播事件对象),scope 参数可选,不一定是必需的.只有在需要时用.
    //scope 属性用在 dispatchEvent 方法中.
    this[type].scope = (scope == undefined ? EventDispatcher.__target : scope);
    //疑问1.等人问吧.

2.removeEventListener 方法.

 

[Copy to clipboard] [ - ]
CODE:
        //如果数组的长度大于0.就证明数组中有元素.
        if (this[type].length > 0) {
            var queue:Array = this[type];
            var len:Number = queue.length;
            //遍历数组.
            for(var i:Number = 0; i < len; i ++){
                //如果数组中的元素(事件侦听器)与参数 listener 相同.
                if(queue[i] == listener){
                    //移除元素(事件侦听器).
                    queue.splice(i, 1);
                    //返回.停止遍历.
                    return;
                }
            }
        }
3.dispatchEvent 方法.

 

[Copy to clipboard] [ - ]
CODE:
    //如果数组的长度大于0.就证明数组中有元素.
    if(this[event.type].length > 0){
        //将 Event 对象的 target 属性指向事件的目标(广播事件对象).
        event.target = EventDispatcher.__target;
        var queue:Array = this[event.type];
        //遍历数组.
        for(var i:String in queue){
            /*
            在 scope 属性所指向的对象中应用函数(事件侦听器).event 对象将作为参数传递给函数(事件侦听器).
            */
            queue[i].apply(queue.scope, [event]);
        }
    }

4.hasEventListener 方法.

 

[Copy to clipboard] [ - ]
CODE:
    //如果数组的长度大于0(也就是已添加了事件侦听器).就返回 true.否则返回 false.
    return (this[type].length > 0);

5.构造函数.

 

[Copy to clipboard] [ - ]
CODE:
    //主要用于获得事件的目标(广播事件对象).只有在不继承此类时才体现作用.
    EventDispatcher.__target = (target == undefined ? this : target);

提示: 当继承此类时.此类中所有的 this 均指向继承此类的对象(事件的目标,广播事件对象).熟知继承概念的对此很好理解.


一般,使自定义类能够自定义事件处理机制最简单的方法是继承 EventDispatcher 类.如果无法扩展(该类已经扩展了另一个类)时.
不能再使用 initialize 方法(因已删除).但可使用以下二个方法:

1.实现 IEventDispatcher 接口,创建 EventDispatcher 成员,来获取此类中的方法.这样做的好处就是可以添加一些自己的实现.

示例:

 

[Copy to clipboard] [ - ]
CODE:
import AS2.events.Event;
import AS2.events.EventDispatcher;
import AS2.events.IEventDispatcher;
class yourClassName implements IEventDispatcher
{
    private var ed:EventDispatcher;
   
    public function yourClassName()
    {
        this.ed = new EventDispatcher(this);
    }
   
    public function addEventListener(type:String, listener:Function, scope:Object):Void
    {
        //这里可以编写一些实现.
        this.ed.addEventListener(type, listener, scope);
    }
    public function removeEventListener(type:String, listener:Function):Void
    {
        //这里可以编写一些实现.
        this.ed.removeEventListener(type, listener);
    }
    public function dispatchEvent(event:Event):Void
    {
        //这里可以编写一些实现.
        this.ed.dispatchEvent(event);
    }
    public function hasEventListener(type:String):Boolean
    {
        //这里可以编写一些实现.
        return this.ed.hasEventListener(type);
    }
}

12下一页
源代码网供稿.
网友评论 (0)
会员中心
设计在线
本站推荐
设计在线之精华