事件管理

1. 认识事件

1.1 什么是事件

事件Event指的是由系统事先设定的、能被对象识别和响应的动作,事件是指对象对于外部动作的响应,当对方发生了某个事件,就会执行于此事件对应的代码。比如用鼠标在一个对象上按下,这个对象预先设定了识别鼠标按下这个事件,就会执行对应的代码。

1.2 事件的分类

1,引擎内置的事件

2,自定义的事件

我们使用的事件可以是引擎内置的事件,也可以是自定义的事件,使用自定义类型的事件叫自定义事件。

2. 引擎内置的事件

LayaAir3.0引擎中的事件主要包含三部分

Laya.Event 事件类型,事件接口,不同的事件类型都要实现此接口。 Laya.EventDispatcher 事件派发,每个传递过来的事件都会由它分发给特定的处理者。 Laya.Handler 事件处理,不同的处理器需实现该接口。

2.1 事件类型 Laya.Event

Laya.Event 是事件类型的集合,当事件发生时Laya.Event对象将作为参数传递给事件侦听器。如图2-1,事件类型请参考API文档。

2-1

(图2-1)

例如 Laya.Event.CLICK:string = "click"CLICK 静态属性用于定义事件对象的type类型属性值为单击事件。这个事件是由鼠标点击触发后系统派发的事件,开发者也可以调用event()方法派发这些事件,如何派发事件会在下面的内容涉及。

2-2

(图2-2)

点击图2-2中3个按钮的任意一个,可以进入对应的功能。我们看看代码是如何使用CLICK 的(以下代码来自“2D入门示例”):

onEnable(): void {

        console.log("IndexRT onEnable")
        //侦听ui按钮点击事件
        this.uiBtn.on(Laya.Event.CLICK, this, () => {
            //点击后,打开UI场景示例
            console.log("uiBtn");
            Laya.Scene.open("scenes/UiMain.ls");
        });

        //侦听物理按钮点击事件
        this.phyBtn.on(Laya.Event.CLICK, this, () => {
            //点击后,打开物理游戏示例
            console.log("phyBtn");
            Laya.Scene.open("scenes/PhysicsGameMain.ls");
        });

        //侦听3D混合按钮点击事件
        this.d3Btn.on(Laya.Event.CLICK, this, () => {
            //点击后,打开3D混合场景示例
            console.log("d3Btn");
            Laya.Scene.open("scenes/D3Main.ls");
        });        
}

2.2 事件派发 Laya.EventDispatcher

事件派发Laya.EventDispatcher模式是侦听模式的一种扩展,由事件驱动,每当有事件产生的时候,由事件分发器Laya.EventDispatcher分发给特定的事件处理器Laya.Handler 处理该事件。Laya.EventDispatcher表示事件发送者、事件捕获传递与分发。

Laya.EventDispatcher 事件分发器是可调度事件类的基类,比如作为基础节点的Node类继承自Laya.EventDispatcher类,只要继承此类就可以作为一个事件发送者发送事件给它的侦听者。那么比如上面示例代码中的Button就是继承自Laya.EventDispatcher,可以用.on的方法来侦听CLICK`事件。

Laya.EventDispatcher 具有如下功能:

2.2.1 事件派发 event

    /**
     * 派发事件。
     * @param type    事件类型。
     * @param data    (可选)回调数据。<b>注意:</b>如果是需要传递多个参数 p1,p2,p3,...可以使用数组结构如:[p1,p2,p3,...] ;如果需要回调单个参数 p ,且 p 是一个数组,则需要使用结构如:[p],其他的单个参数 p ,可以直接传入参数 p。
     * @return 此事件类型是否有侦听者,如果有侦听者则值为 true,否则值为 false。
     */
    event(type: string, data: any = null)

用于派发事件,例如我们可以在代码中来派发一个CLICK事件 :

//侦听ui按钮点击事件
this.uiBtn.on(Laya.Event.CLICK, this, () => {
    //点击后,打开UI场景示例
    console.log("uiBtn");
    Laya.Scene.open("scenes/UiMain.ls");
});

//uiBtn自己派发一个点击事件,由于上面有侦听,则立即执行打开uiMain场景
this.uiBtn.event(Laya.Event.CLICK);

2.2.2 持续事件侦听 on

    /**
     * 使用 EventDispatcher 对象注册指定类型的事件侦听器对象,以使侦听器能够接收事件通知。
     * @param type        事件的类型。
     * @param caller    事件侦听函数的执行域。
     * @param listener    事件侦听函数。
     * @param args        (可选)事件侦听函数的回调参数。
     * @return 此 EventDispatcher 对象。
     */
    on(type: string, caller: any, listener: Function, args: any[] = null)

用于向事件派发器注册指定类型的事件侦听器,使事件侦听器能够接收事件通知。当侦听到事件后,会调用作用域 caller 的回调方法 listener

上述2.2.1的示例中 this.uiBtn.on 是使用了持续侦听。

2.2.3 单次事件侦听 once

    /**
     * 使用 EventDispatcher 对象注册指定类型的事件侦听器对象,以使侦听器能够接收事件通知,此侦听事件响应一次后自动移除。
     * @param type        事件的类型。
     * @param caller    事件侦听函数的执行域。
     * @param listener    事件侦听函数。
     * @param args        (可选)事件侦听函数的回调参数。
     * @return 此 EventDispatcher 对象。
     */
    once(type: string, caller: any, listener: Function, args: any[] = null)

用于向事件分发器注册指定类型的事件侦听器,使事件侦听器能够接收事件通知,事件侦听器响应一次后会自动移除。例如上述2.2.1示例中的按钮的侦听方式也可以改为单次事件侦听:

//侦听一次ui按钮点击事件
this.uiBtn.once(Laya.Event.CLICK, this, () => {
    //点击后,打开UI场景示例
    console.log("uiBtn");
    Laya.Scene.open("scenes/UiMain.ls");
});

2.2.4 删除指定的侦听 off

    /**
     * 从 EventDispatcher 对象中删除侦听器。
     * @param type        事件的类型。
     * @param caller    事件侦听函数的执行域。
     * @param listener    事件侦听函数。
     * @return 此 EventDispatcher 对象。
     */
    off(type: string, caller: any, listener: Function, onceOnly: boolean = false)

用于从事件分发器对象中删除侦听器:

onDestroy(): void {
    //删除ui按钮的侦听
    this.uiBtn.off(Laya.Event.CLICK, this);     
}

当这个场景删除销毁时,最好删除按钮的事件侦听,保证释放掉所有引用。

2.2.5 删除指定事件类型的所有侦听 offAll

    /**
     * 从 EventDispatcher 对象中删除指定事件类型的所有侦听器。
     * @param type    (可选)事件类型,如果值为 null,则移除本对象所有类型的侦听器。
     * @return 此 EventDispatcher 对象。
     */
    offAll(type: string = null)

用于从事件分发器对象中删除指定事件类型的所有侦听器。例如,uiBtn按钮注册了多个事件的侦听,可以用offAll方法来一次性删除所有点击事件的侦听 :

onDestroy(): void {
    //删除ui按钮的侦听
    this.uiBtn.offAll(Laya.Event.CLICK);    
}

2.2.6 删除指定作用域的所有侦听 offAllCaller

    /**
     * 移除caller为target的所有事件侦听
     * @param    caller caller对象
     */
    offAllCaller(caller: any)

用于从事件分发器对象中删除指定作用域的所有侦听器。例如,uiBtn按钮注册了多个事件的侦听,可以用offAllCaller方法来一次性删除this作用域上的所有侦听 :

onDestroy(): void {
    //删除this作用域的侦听
    this.uiBtn.offAllCaller(this);
}

2.2.7 检查是否已注册侦听 hasListener

用于判断事件分发器对象是否为特定类型的事件注册了侦听器。

    /**
     * 检查 EventDispatcher 对象是否为特定事件类型注册了任何侦听器。
     * @param    type 事件的类型。
     * @return 如果指定类型的侦听器已注册,则值为 true;否则,值为 false。
     */
    hasListener(type: string)

例如:

if( this.uiBtn.hasListener( Laya.Event.CLICK ) )
    console.log("uiBtn有点击事件侦听");

2.3 事件处理 Laya.Handler

当侦听到事件后,用来处理事件的处理器

  • 处理器的属性包括:

    1,caller: Object | null; 执行域

    2,method: Function | null 执行方法

    3,args: any[] | null 参数

    4,once = false 表示是否只执行一次。如果为true,回调后执行recover()进行回收,回收后会被再利用,默认为false

  • 处理器的方法包括:

    1,create() 从对象池内创建一个Handler

Laya.Handler 事件处理器,推荐使用Laya.Handler.create()方法从对象池创建,以减少对象创建消耗。当创建的Handler对象不再使用后,可使用Laya.Handler.recover()将其回收到对象池,回收后不要再使用此对象,否则会导致不可预料的错误。需要注意的是,由于鼠标事件也使用了对象池,不正确的回收以及调用,可能会影响事件的执行。

onAwake(): void {
    console.log("Game Start");
    this.Tab.selectHandler = Laya.Handler.create(this,(index:number)=>{
        console.log(index);
    })
}

Tab会侦听用户点了某个标签,并从对象池创建一个处理器。

​ 2,clear(): Handler 清理对象引用

this.Tab.selectHandler.clear();

​ 3,recover(): void 清理并回收到 Handler 对象池内

this.Tab.selectHandler.recover();

​ 4,run(): any 执行处理器

this.Tab.selectHandler.run(); //可以自行调用run()

​ 5,runWith(data: any): any 执行处理器,并携带额外数据

this.Tab.selectHandler.runWith(1); //可以自行调用runWith(),并传入参数1

​ 6,setTo(caller: any, method: Function | null, args: any[] | null, once = false): Handler 设置此对象的指定属性值。

onAwake(): void {
    console.log("Game Start");
    this.Tab.selectHandler = Laya.Handler.create(this,(index:number)=>{
        // console.log(index);
    })
    this.Tab.selectHandler.setTo(this,(index:number)=>{
        console.log(index);
    },[],false);
}

可以自行更改指定的属性

3. 自定义的事件

大多数情况下,开发者使用的都是引擎内置的事件,有时也需要使用自定义的事件。下面举一个例子来说明派发自定义的事件。

在LayaAir IDE中,新建一个2D空项目,在Scene2D下新建一个自定义的组件脚本,并添加如下代码:

onAwake(): void {
    //侦听自定义的事件"Click"
    this.owner.on("Click",this,()=>{
        console.log("侦听到自定义的“Click”事件");
    })
}

//鼠标点击后执行,发送Click事件。
onMouseClick(evt: Laya.Event): void {
    //自定义的事件
    this.owner.event("Click");
}

示例中的this.owner就是Scene2D,当鼠标点击场景后,就会派发自定义的事件"Click",这个"Click"就是自定义的事件。当侦听到"Click"时,就会打印"侦听到自定义的“Click”事件"的日志。

Copyright ©Layabox 2022 all right reserved,powered by LayaAir Engine更新时间: 2023-07-29 17:15:05

results matching ""

    No results matching ""