我一般是新的JavaScript和编程,以及我对物体和事件的一些问题。
说我有一个对象:
var computer = {
keyboard: {}
}
我正在寻找的是登记事件键盘对象的方式:
computer.keyboard.registerEvent( "keyEscape" );
火灾的事件:
computer.keyboard.dispatchEvent( "keyEscape" );
和创建事件处理程序:
computer.keyboard.addEventListener( "keyEscape", function() {...} );
我知道如何与DOM元素,但不是对象做到这一点。 这是不是可以用JavaScript来实现(可能使用jQuery的帮助下)?
甚至指导半点将不胜感激。
Answer 1:
如果你想建立一个完全独立的事件系统不依赖于DOM事件,你可以有这样的事情用反应器模式
function Event(name){
this.name = name;
this.callbacks = [];
}
Event.prototype.registerCallback = function(callback){
this.callbacks.push(callback);
}
function Reactor(){
this.events = {};
}
Reactor.prototype.registerEvent = function(eventName){
var event = new Event(eventName);
this.events[eventName] = event;
};
Reactor.prototype.dispatchEvent = function(eventName, eventArgs){
this.events[eventName].callbacks.forEach(function(callback){
callback(eventArgs);
});
};
Reactor.prototype.addEventListener = function(eventName, callback){
this.events[eventName].registerCallback(callback);
};
使用它像DOM事件模型
var reactor = new Reactor();
reactor.registerEvent('big bang');
reactor.addEventListener('big bang', function(){
console.log('This is big bang listener yo!');
});
reactor.addEventListener('big bang', function(){
console.log('This is another big bang listener yo!');
});
reactor.dispatchEvent('big bang');
住在JSBin
Answer 2:
如果你不希望实现自己的事件处理机制,你可能会喜欢我的做法。 你会得到所有你知道,从通常的DOM事件的特征(preventDefault()方法为例),我认为它更轻便,因为它使用了已经实现的DOM事件处理浏览器的功能。
只要创建你的对象的构造正常的DOM事件目标对象,并通过所有的EventTarget接口调用到DOM事件目标对象:
var MyEventTarget = function(options) {
// Create a DOM EventTarget object
var target = document.createTextNode(null);
// Pass EventTarget interface calls to DOM EventTarget object
this.addEventListener = target.addEventListener.bind(target);
this.removeEventListener = target.removeEventListener.bind(target);
this.dispatchEvent = target.dispatchEvent.bind(target);
// Room your your constructor code
}
// Create an instance of your event target
myTarget = new MyEventTarget();
// Add an event listener to your event target
myTarget.addEventListener("myevent", function(){alert("hello")});
// Dispatch an event from your event target
var evt = new Event('myevent');
myTarget.dispatchEvent(evt);
还有一个的jsfiddle片段与浏览器进行测试。
Answer 3:
Necroposting一点点在这里,但我只是写这样的事情,昨晚 - 超级简单,并根据关Backbone.js的活动模块:
EventDispatcher = {
events: {},
on: function(event, callback) {
var handlers = this.events[event] || [];
handlers.push(callback);
this.events[event] = handlers;
},
trigger: function(event, data) {
var handlers = this.events[event];
if (!handlers || handlers.length < 1)
return;
[].forEach.call(handlers, function(handler){
handler(data);
});
}
};
这种方法是非常简单的,可扩展,使您可以在它上面建立一个更复杂的事件系统,如果你需要。
使用EventDispatcher
是简单的:
function initializeListeners() {
EventDispatcher.on('fire', fire); // fire.bind(this) -- if necessary
}
function fire(x) {
console.log(x);
}
function thingHappened(thing) {
EventDispatcher.trigger('fire', thing);
}
随着一些简单的命名空间,你就可以通过模块之间的基本活动自如!
Answer 4:
您可以使用JQuery做到这一点。
对于订阅您的自定义事件:
$(computer.keyboard).on('keyEscape', function(e){
//Handler code
});
投掷您的自定义事件:
$(computer.keyboard).trigger('keyEscape', {keyCode:'Blah blah'});
可能是没有做到这一点的最好办法,但你也可以创建你的方法(的addEventListener,则dispatchEvent,...)函数将包装JQuery的逻辑,同时支持本地查找API和JQuery。
Answer 5:
最有可能的,你需要一个事件机制几种通信对象之间的媒介。
下面有你如何能做到这一点:
/** * EventfulObject constructor/base. * @type EventfulObject_L7.EventfulObjectConstructor|Function */ var EventfulObject = function() { /** * Map from event name to a list of subscribers. * @type Object */ var event = {}; /** * List of all instances of the EventfulObject type. * @type Array */ var instances = []; /** * @returns {EventfulObject_L1.EventfulObjectConstructor} An `EventfulObject`. */ var EventfulObjectConstructor = function() { instances.push(this); }; EventfulObjectConstructor.prototype = { /** * Broadcasts an event of the given name. * All instances that wish to receive a broadcast must implement the `receiveBroadcast` method, the event that is being broadcast will be passed to the implementation. * @param {String} name Event name. * @returns {undefined} */ broadcast: function(name) { instances.forEach(function(instance) { (instance.hasOwnProperty("receiveBroadcast") && typeof instance["receiveBroadcast"] === "function") && instance["receiveBroadcast"](name); }); }, /** * Emits an event of the given name only to instances that are subscribed to it. * @param {String} name Event name. * @returns {undefined} */ emit: function(name) { event.hasOwnProperty(name) && event[name].forEach(function(subscription) { subscription.process.call(subscription.context); }); }, /** * Registers the given action as a listener to the named event. * This method will first create an event identified by the given name if one does not exist already. * @param {String} name Event name. * @param {Function} action Listener. * @returns {Function} A deregistration function for this listener. */ on: function(name, action) { event.hasOwnProperty(name) || (event[name] = []); event[name].push({ context: this, process: action }); var subscriptionIndex = event[name].length - 1; return function() { event[name].splice(subscriptionIndex, 1); }; } }; return EventfulObjectConstructor; }(); var Model = function(id) { EventfulObject.call(this); this.id = id; this.receiveBroadcast = function(name) { console.log("I smell another " + name + "; and I'm model " + this.id); }; }; Model.prototype = Object.create(EventfulObject.prototype); Model.prototype.constructor = Model; // ---------- TEST AND USAGE (hopefully it's clear enough...) // ---------- note: I'm not testing event deregistration. var ob1 = new EventfulObject(); ob1.on("crap", function() { console.log("Speaking about craps on a broadcast? - Count me out!"); }); var model1 = new Model(1); var model2 = new Model(2); model2.on("bust", function() { console.log("I'm model2 and I'm busting!"); }); var ob2 = new EventfulObject(); ob2.on("bust", function() { console.log("I'm ob2 - busted!!!"); }); ob2.receiveBroadcast = function() { console.log("If it zips, I'll catch it. - That's me ob2."); }; console.log("start:BROADCAST\n---------------"); model1.broadcast("crap"); console.log("end :BROADCAST\n---------------\n-\n-\n"); console.log("start:EMIT\n---------------"); ob1.emit("bust"); console.log("end:EMIT\n---------------");
<h1>...THE SHOW IS ON YOUR CONSOLE!</h1>
Answer 6:
下面是一个简单的扩展的穆赫辛的回答 ,表现为明显的短例子。
他都可以响应功能封装成一个React()
附加功能removeEventListener()
和全实例中,呈现为一个HTML文件(或看到它的jsfiddle )。
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>JS Bin</title>
<!--https://jsfiddle.net/romleon/qs26o3p8/-->
</head>
<body>
<script>
function Reactor() {
function Event(name) {
this.name = name;
this.callbacks = [];
}
Event.prototype.registerCallback = function(callback) {
this.callbacks.push(callback);
};
Event.prototype.unregisterCallback = function(callback) {
var array = this.callbacks,
index = array.indexOf(callback);
if (index > -1)
array.splice(index, 1);
}
this.events = {};
this.registerEvent = function(eventName) {
var event = new Event(eventName);
this.events[eventName] = event;
};
this.dispatchEvent = function(eventName, eventArgs) {
var events = this.events
if (events[eventName]) {
events[eventName].callbacks.forEach(function(callback) {
callback(eventArgs);
});
}
else
console.error("WARNING: can't dispatch " + '"' + eventName + '"')
};
this.addEventListener = function(eventName, callback) {
this.events[eventName].registerCallback(callback);
};
this.removeEventListener = function(eventName, callback) {
var events = this.events
if (events[eventName]) {
events[eventName].unregisterCallback(callback);
delete events[eventName];
}
else
console.error("ERROR: can't delete " + '"' + eventName + '"')
};
}
/*
demo of creating
*/
var reactor = new Reactor();
reactor.registerEvent('big bang');
reactor.registerEvent('second bang');
/*
demo of using
*/
log("-- add 2 event's listeners for 'big bang' and 1 for 'second bang'")
var callback1 = function() {
log('This is big bang listener')
}
reactor.addEventListener('big bang', callback1);
reactor.addEventListener('big bang', function() {
log('This is another big bang listener')
});
reactor.addEventListener('second bang', function() {
log('This is second bang!')
});
log("-- dipatch 'big bang' and 'second bang'")
reactor.dispatchEvent('big bang');
reactor.dispatchEvent('second bang');
log("-- remove first listener (with callback1)")
reactor.removeEventListener('big bang', callback1);
log("-- dipatch 'big bang' and 'second bang' again")
reactor.dispatchEvent('big bang');
reactor.dispatchEvent('second bang');
function log(txt) {
document.body.innerHTML += txt + '<br/>'
console.log(txt)
}
</script>
</body>
</html>
文章来源: Custom Events Model without using DOM events in JavaScript