用JavaScript编写一个自定义事件调度程序
Write a custom event dispatcher in JavaScript?
如何在JavaScript中向自己类的对象添加事件侦听器并从中调度事件
在ActionScript3中,我可以简单地从Sprite/DisplayObject继承并使用那里可用的方法。像这样:
// ActionScript-3:
// I can add event listeners to all kinds of events
var mySprite: Sprite = new MySprite();
mySprite.addEventListener("my_menu_item_click", onMenuItemClick);
// later I can dispatch an event from one of my objects
mySprite.dispatchEvent(new Event("my_menu_item_click", ...));
我希望在JavaScript中也有同样的功能。到目前为止,我对window.addEventListener(...)
和document.addEventListener(...)
有所了解。到目前为止,我有自己的JavaScript Sprite类,我想用它来调度我自己的事件。
// JavaScipt:
function Sprite()
{
this.x = 0;
this.y = 0;
// ...
}
由于这两种语言似乎都是如此";类似的";我想我需要从某个类继承事件?还是我必须使用一些全局变量,如窗口和/或文档?
我在这里使用HTML5。我只有1个画布和一堆绘制在上面并对用户输入做出反应的精灵。我希望一个精灵A订阅另一个精灵B的事件。但不订阅第三个精灵C的事件。
我尝试将这些方法添加到我的Sprite类中并成功了
当然还没有完成,但至少它起作用了
这就是我想要的。
function Sprite()
{
// ...
this.eventListeners = new Array();
this.addEventListener = function(type, eventHandler)
{
var listener = new Object();
listener.type = type;
listener.eventHandler = eventHandler;
this.eventListeners.push(listener);
}
this.dispatchEvent = function(event)
{
for (var i = 0; i < this.eventListeners.length; i++)
if (event.type == this.eventListeners[i].type)
this.eventListeners[i].eventHandler(event);
}
}
这是一种"函数"方法,我不喜欢在javascript中使用"new"answers"This"。我喜欢普通对象、对等对象或扩展对象。
// Some helper functions, should be imported from a different file
const partial = fn => (...pargs) => (...args) => fn.apply(null, [...pargs, ...args]);
const partialRight = fn => (...pargs) => (...args) => fn.apply(null, [...args, ...pargs.reverse()]);
// Module starts here
const on = (listeners, type, listener, once) => {
if (!listeners[type]) {
listeners[type] = [];
}
if (listeners[type].indexOf(listener) < 0) {
listener.once = once;
listeners[type].push(listener);
}
};
const once = partialRight(on)(true);
const off = (listeners, type, listener) => {
const listenerType = listeners[type];
if (listenerType && listenerType.length) {
const index = listenerType.indexOf(listener);
if (index !== -1) {
listenerType.splice(index, 1);
}
}
if ((listenerType && !listenerType.length) || !listener) {
delete listeners[type];
}
};
const emit = (listeners, type, ...data) => {
if (listeners[type]) {
listeners[type].forEach(listener => {
listener.apply(null, data);
if (listener.once) {
off(listeners, type, listener);
}
});
}
};
// you could use "export default () => {}" to make it an importable module
const eventEmitter = () => {
const listeners = {};
return {
on: partial(on)(listeners),
once: partial(once)(listeners),
off: partial(off)(listeners),
emit: partial(emit)(listeners),
};
};
const myObj = Object.create(Object.assign({}, eventEmitter()));
myObj.on('hello', name => console.log(name));
setTimeout(() => {
myObj.emit('hello', 'Csaba')
}, 2000)
您可以在JS中使用Event和CustomEvent对象执行几乎相同的操作:
var event = new Event('build');
// Listen for the event.
elem.addEventListener('build', function (e) { ... }, false);
// Dispatch the event.
elem.dispatchEvent(event);
来源:MDN(https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Creating_and_triggering_events)
您可以自己制作,这个是通用的,非常简单。实际上我自己也用:D
这就是您将获得的功能。
- addEventListener()
- removeEventlistener()
- dispatchEvent()(或者你想怎么称呼它)
这个函数将向对象添加所需的方法,同时返回一个可以调度事件的函数。
// Snippet =========================================
function createEventDispatcher(o) {
var L = o.__listeners = {};
o.addEventListener = function(n, fn) { L[n] = L[n] || []; L[n].push(fn); };
o.removeEventListener = function(n, fn) { var a = L[n]; for (var i = 0; i < a.length; i++) if (a[i] === fn) a.splice(i, 1);};
return function() { var a = Array.prototype.slice.call(arguments); var l = L[a.shift()]; if (l) for (var i = 0; i < l.length; i++) l[i].apply(l[i], a)};
}
:
// Simplified example of usage =========================================
function App(){
// Add functionality
var dispatchEvent = createEventDispatcher(this); // Call snippet
// Use functionality
var count = 0;
setInterval(function(){
dispatchEvent("something",{msg:"hello",count:count++});
},100);
}();
// Somewhere outside your App
function onSomething(event){
console.log(event.msg + "["+event.count+"]");
if(event.count >= 10){
// Remove eventlistener
myApp.removeEventListener("something",onSomething);
}
}
var myApp = new App();
myApp.addEventListener("something",onSomething);
// Easy
https://jsfiddle.net/squadjot/0n2nby7k/
如果您想从对象中删除所有侦听器,只需执行以下操作即可。
myApp.__listeners = {};
- 从HTTPGET返回一个自定义对象列表,以便在Angular 2应用程序中使用
- SuiteScript2.0-包括一个自定义文件
- Wordpress在播放器旁边播放一个自定义的下载按钮,而不是下载
- SuiteScript:如何有一个自定义的数据字段来从数据库加载信息
- 如何使用其他自定义指令中的元素标记作为另一个自定义指令的模板
- 调用另一个自定义指令的角度自定义指令
- 我想做一个自定义的dojo JsonRest商店,有一部分我没有'我不明白
- 如何调用另一个js文件中的函数或触发一个自定义事件,该事件将参数作为Jquery中的数据对象传递
- 我想知道如何创建一个自定义对话框,当点击按钮时会弹出
- 在brunc.io中创建一个自定义JS目录
- 如何使用Angular 1.5组件将属性求值为字符串,这是一个自定义函数
- 为谷歌工作表创建一个自定义函数
- Vaadin:调用一个自定义的JavaScript函数
- Tinymce-创建一个自定义的javascript保存按钮
- Wordpress创建一个自定义休息服务
- 如何在Angular 1.3.6上创建一个自定义过滤器来搜索嵌套数组
- 当我点击一个asp表元素时,我如何制作一个自定义弹出窗口
- 我对javascript中的一个自定义函数感到困惑,该函数将对象作为参数获取
- 为什么我们必须注册一个自定义元素
- 导入 serval WebComponent 时,上一个自定义元素被下一个元素覆盖