自己搞了一个简单粗暴的全局事件派送(全局广播) 7月15日更新

最近要用全局事件派送,奈何官方大神还在讨论设计模式,所以自己照葫芦画瓢搞了一个

友情提示:本人英语水平很低!逻辑思维很差!设计模式一个都不懂!只是照着我的想法做出来了,所以大神勿喷 :joy:

友情提示:本人英语水平很低!逻辑思维很差!设计模式一个都不懂!只是照着我的想法做出来了,所以大神勿喷 :joy:

友情提示:本人英语水平很低!逻辑思维很差!设计模式一个都不懂!只是照着我的想法做出来了,所以大神勿喷 :joy:

里面很多变量名都是查英语词典拼凑的,所以同学们,大神们,别喷我:joy:

重要的事情说三遍:joy::joy::joy::joy:

所以可能会有很多问题,欢迎大家反馈,当然你也可以根据自己需要来进行修改,因为简单粗暴,所以没啥技术含量只不过节省有和我相同需要的同学的时间

目前实现的功能

1.添加监听器(事件名称,回调函数,target)

cc.director.GlobalEvent.addMonitor(eventName, function (event) {
   //获取事件传递的数据
   var data = event.data;
   //事件停止传递
   event.stopSend();
}, this);

2.添加一次性监听器(事件名称,回调函数,target) 这个就是只触发一次

cc.director.GlobalEvent.addMonitorOnce(eventName, function (event) {
   //获取事件传递的数据
   var data = event.data;
   //事件停止传递
   event.stopSend();
}, this);

3.发送事件(事件名称,事件数据)

cc.director.GlobalEvent.sendEvent(eventName, data);

4.移除监听器(事件名称, target)

cc.director.GlobalEvent.removeMonitor(eventName, target);

5.移除所有监听器

cc.director.GlobalEvent.removeAllMonitor();

6.自定义事件派送顺序(从上倒下或者从下到上,当然这里的顺序是根据监听器添加的顺序做的,因为测试的时候添加监听器都是在onLoad里进行的)

从上到下

从下到上

###7月15日更新
以前移除监听器是通过事件名把整个事件全部移除了:joy:,现在修改为移除某个target上的事件监听,不会影响其他相同事件的监听和触发

###7月14日更新

感谢 @_GK@hp134800两位同学的帮助和指点,修复了若干因本人智商导致的错误:joy:

比如

比如

以及一些其他小问题

###基本思路

就是在cc.dirctor上添加一个事件管理器(在Canvas的onLoad里进行,这样能保证Canvas的所有子节点以及层级管理器里在Canvas下面的节点都能添加和发送事件),并且如果是在onLoad阶段添加的事件,统一放到start阶段进行派送,因为我这个是根据事件的添加顺序进行派送的,并且派送必须在发生在添加之后,但是有可能派送事件发生在监听事件之前导致事件派送失效,所以为了保证理想的流程,就把onLoad阶段添加的事件统一放到start阶段派送(再次感谢@hp134800同学提供的思路)

简单demo

globalEvent.zip (2.8 MB)

使用方法:

把demo里的GlobalEvent添加为Canvas的第一个组件(或者添加到第一个执行onLoad的节点,就是层级管理器里最最最上面的那个节点),然后设置事件传递的顺序就行了,我不知道creator切换场景的时候会不会销毁事件列表以及监听器的回调函数和target,所以最好是在脚本里添加onDestroy生命周期回调,并且在回调里调用cc.director.GlobalEvent.removeAllMonitor();手动删除所有事件列表,如果onDestroy里不行,就用onDisable

仅供参考和测试,如果使用途中 造成任何损失,概不赔偿:joy::joy:

希望大家有啥问题可以给我说,如果我有能力修改,肯定第一次时间修改后上传

8赞

讚一個,謝謝分享!

:joy: 反正我自己都觉得写的太差,反正我觉得能用就行

js零基础真心受教,又学到了很多js的语法。但是这里要双等号或者三个等号吧。不然会不管什么eventName都能进入。而且都只调用第一个。我使用的时候纳闷很久。

对的,非常感谢指出,有可能那个严重的bug就是这里造成的,非常感谢:hamburger:,怪我太粗心了

我又来了我又遇到一个挺严重bug了,就是注册两个广播第一个名字就叫’name1’,第二个就叫’name2’,然后问题来了,name2的回调函数被调用了两次。看了你的代码很久,没毛病。不过还是找到了原因了如图原版这里没有return。于是本来i已经等于length-1了可是在push进去一个新的,导致length又多加了1,所以循环还没跳出。所以就跑进这里面了。

感谢感谢,非常感谢,回去我修改好重新修改好上传,我就是太粗心了:watermelon:

我理解的就是 1 注册个EventManager 到 cc.director下,这个EventManager有add remove dispatch 方法。 2 再别处通过cc.director.EventManager 注册回调。 3diapatch 出去

对的,所以现在还有问题,因为可能会出现派送事件发生在订阅事件之前,所以现在仅供参考:joy:最好不要使用到项目中

这个好办,注册在onload中,派送至少在start() 之后或者动态

感谢,这是个好办法,我已经用到demo里面了:grin:

吐槽: creator 的事件分发 跟 cocos2d-x 的又不一样, 特别是那个dispatchEvent. - -|||

爬贴找到楼主的方案。看了下demo, 感觉有点复杂。

最后, 我是这样实现的:

// helper.js

var _node = null;
var helper = {
setHelperNode: (node) => {
_node = node;
},
emit: function(sender, eventName, data) {
_node.emit(eventName, data);
},
on: function(receiver, eventName, callback) {
_node.on(eventName, callback, receiver);
},
off: (receiver, eventName) => {
_node.off(eventName, element.callback, receiver);
}
};
module.exports = helper;
// end of helper

test:
// A.js
var helper = require(‘helper’);

onLoad(): function() {
// …
var self = this;
helper.on(self.node, ‘TestEvent’, function(event) {
cc.log(‘get :’, event.detail.msg);
});
// …
}

// B.js
var helper = require(‘helper’);

onLoad(): function() {
// …
var self = this;
setTimeout(function(){
helper.emit(self.node, ‘TestEvent’, { msg: ‘11111111111111’ });
}, 2000);
// …
}

楼主说的是观察者模式?有点没看懂楼主的思路,我们项目是这样的。

// 全局通知
window.Notification = {
    _eventMap: [],

    on: function(type, callback, target) {
        if (this._eventMap[type] === undefined) {
            this._eventMap[type] = [];
        }
        this._eventMap[type].push({ callback: callback, target: target });
    },

    emit: function(type, parameter) {
        var array = this._eventMap[type];
        if (array === undefined) return;
        
        for (var i = 0; i < array.length; i++) {
            var element = array[i];
            if (element) element.callback.call(element.target, parameter);
        }
    },

    off: function(type, callback) {
        var array = this._eventMap[type];
        if (array === undefined) return;

        for (var i = 0; i < array.length; i++) {
            var element = array[i];
            if (element && element.callback === callback) {
                array[i] = undefined;
                break;
            }
        }
    },

    offType: function(type) {
        this._eventMap[type] = undefined;
    },
};
5赞

差不多就是观察者模式,就是全局广播:grin:

简单易懂,谢谢分享

收藏 收藏

我都改用凤凰花开的那个了,我写这个太麻烦了

观察者模式,用了快三年了,一直觉得不错,有兴趣的可以去看看pureMVC ,很nice的一个框架体系,尤其是做大型游戏,简直跟开了挂一样

帮忙看一下这个是什么原因呀???

Cannot read property ‘call’ of undefined;at socketTask.onmessage callback function
TypeError: Cannot read property ‘call’ of undefined
at Object.emit (http://127.0.0.1:59601/game/src/project.2d043.js:1331:39)
at peer_enter_room (http://127.0.0.1:59601/game/src/project.2d043.js:1690:380)
at e (http://127.0.0.1:59601/game/src/project.2d043.js:3189:258)
at WebSocket.socket.onmessage (http://127.0.0.1:59601/game/src/project.2d043.js:3204:52)
at Function. (http://127.0.0.1:59601/game/libs/weapp-adapter/WebSocket.js:72:15)
at _e. (http://127.0.0.1:59601/game/dev/WAGame.js:1:109814)
at _e.emit (http://127.0.0.1:59601/game/dev/WAGame.js:1:153856)
at http://127.0.0.1:59601/game/dev/WAGame.js:1:212282
at http://127.0.0.1:59601/game/dev/WAGame.js:1:146825
at e (http://127.0.0.1:59601/game/gamePage.html:1:42774)
console.error @ VM6817:1

官方 都实现的好好的了。。。何必自己撸一个。。。直接用 Node 啊

1赞