JavaScript事件派发和监听机制实现

使用场景

H5游戏开发,跨JS文件事件监听及派发,游戏引擎cocoscreator v2.4.2,开发语言JavaScript。

代码实现

/**
 * 事件派发机制	EventListener.js             @半世   2021/05/25
 */

const EventListener = {
    //事件表
    Regsiter: {},

    //注册事件
    on: function(name, method){
        if(!this.Regsiter.hasOwnProperty(name)){
            this.Regsiter[name] = [];
        }
        this.Regsiter[name].push(method);
    },

    //触发事件
    fire: function(name){
        if(this.Regsiter.hasOwnProperty(name)){
            let handlerList = this.Regsiter[name];
            //遍历回调函数列表(同一个事件,多个回调监听)
            for(let i = 0; i < handlerList.length; ++i){
                let handler = handlerList[i];
                let args = [];
                //参数处理
                for(let j = 1; j < arguments.length; ++j){
                    args.push(arguments[j]);
                }
                //调用事件回调
                handler.apply(this, args);
            }
        }
    },

    //注销事件
    off: function(name, method){
        if(this.Regsiter.hasOwnProperty(name)){
        	//同一个事件,可能会触发多个处理函数,所以,在注册时以数组的形式存储事件,销毁时,亦同。
            let handlerList = this.Regsiter[name];
            for(let i = 0; i < handlerList.length; ++i){
                console.log('循环查找某个事件进行注销', i, (handlerList[i]===method));
                if(handlerList[i] === method){
                    console.log('注销成功')
                    handlerList.splice(i , 1);
                }
            }
        }
    }
};

module.exports = EventListener;

代码解析

上方代码有两个重点:

1、函数的 arguments 隐藏参数,函数在声明的时候,都会自带一个 arguments 属性,里面以数组的形式存放该函数在被调用时,所传递过来的参数。所以,我们再处理 fire 函数的时候,可以通过该属性,拿取传递过来的各种参数。

2、JS的 apply() 方法,简单来讲,该方法就是用来改变当前代码运行环境的 this 指向。具体可以看我的另一篇文档。JavaScript 中 call()、apply()、bind() 的用法

注册监听事件

/**
 * 游戏主逻辑控制类	GameManager.js             @半世   2021/05/21
 */
 let EventListener = require('../event/EventListener');
cc.Class({
    extends: cc.Component,

    properties: {
    },

    // LIFE-CYCLE CALLBACKS:

	// cocoscreator 自带的声明周期函数 onLoad() 我比较习惯于在这里做一些初始化工作以及事件监听
    onLoad () {
        //正确绑定
        this.test_event_callback = this.showPanelGameOver.bind(this);
        EventListener.on('test_event', this.test_event_callback);
        //错误绑定
        EventListener.on('test_event2', this.showPanelGameOver.bind(this));
    },

    // start() {},


    eventOff(){
    	//正确销毁
        EventListener.off('test_event', this.test_event_callback);
        //错误销毁
        EventListener.off('test_event2', this.test_event_callback.bind(this));
    },

    // update (dt) {},
});

代码解析

上面有一个两个重点:

1、bind() 方法的使用,函数 bind 之后,返回值是一个函数,需要用个变量存储一下,否则后面销毁的时候,你再次通过 bind 形式去销毁,销毁的是另外一个函数了, 事件监听表里面是找不到这个新生成的函数的。

2、函数的比较,事件在销毁的时候会进行函数 === 判断。这里判断两个函数是否相等,是通过比较两个函数的指针,所指向的地址(栈地址)是否为同一个地址。

触发事件

/**
 * 游戏主界面逻辑控制类	PanelMain.js             @半世   2021/05/21
 */
let EventListener = require('../event/EventListener');
cc.Class({
    extends: cc.Component,

    properties: {
    },

    // LIFE-CYCLE CALLBACKS:
	
    // onLoad () {},

	//声明周期函数
    start() {
    	//触发事件
        EventListener.fire('test_event', 'a', 'b', 10086);
    },

    // update (dt) {},
});

备注:事件监听机制是开发过程中十分常用的一个机制,代码量虽然不大,但涉及到的小知识点挺多的。关于 JS 的 this 绑定,以及模块的导出和导入,可以参考一下我的其他帖子。

JavaScript 中 call()、apply()、bind() 的用法

node.js模块化(module.exports/exports/require)

至此,结束。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值