自定义事件模型,不使用JavaScript中的DOM事件

NTD*_*ave 41 javascript events object handler

我是JavaScript和编程的新手,我对对象和事件有一些疑问.

说我有一个对象:

var computer = {
    keyboard: {}
}
Run Code Online (Sandbox Code Playgroud)

我正在寻找的是一种向键盘对象注册事件的方法:

computer.keyboard.registerEvent( "keyEscape" );
Run Code Online (Sandbox Code Playgroud)

点燃活动:

computer.keyboard.dispatchEvent( "keyEscape" );
Run Code Online (Sandbox Code Playgroud)

并创建事件处理程序:

computer.keyboard.addEventListener( "keyEscape", function() {...} );
Run Code Online (Sandbox Code Playgroud)

我知道如何使用DOM元素而不是对象.这是可以用JavaScript完成的(也许是在JQuery的帮助下)?

即使是最轻微的指导也会受到极大的赞赏.

Moh*_*sen 50

如果你想在不依赖DOM事件的情况下创建一个完全独立的事件系统,你可以使用reactor模式进行类似的事情

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);
};
Run Code Online (Sandbox Code Playgroud)

像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');
Run Code Online (Sandbox Code Playgroud)

住在JSBin

  • 这里警告一下,没有考虑当你想摆脱回调时会发生什么。如果没有它,您可能会遇到内存泄漏以及您可能期望在实际处理事件时已处理的对象的其他问题。 (2认同)

Tor*_*ben 36

如果您不想实现自己的事件处理机制,您可能会喜欢我的方法.您将从常见的DOM事件(例如preventDefault())中获得您所知道的所有功能,并且我认为它更轻量级,因为它使用已经实现的浏览器DOM事件处理功能.

只需在对象的构造函数中创建一个普通的DOM EventTarget对象,并将所有EventTarget接口调用传递给DOM EventTarget对象:

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);
Run Code Online (Sandbox Code Playgroud)

还有一个JSFiddle代码片段可以使用您的浏览器进行测试.

  • 像魅力一样工作.你应该获得更多的选票. (5认同)
  • 解决方案本身并不老式——只有创建“myevent”的方式才是。我已经更新了示例代码,以便它现在使用现代方式来创建事件。 (3认同)

小智 15

您可以EventTarget像某些人建议的那样简单地创建一个新实例,而不必创建 DOM 对象,如下所示:

const target = new EventTarget();
target.addEventListener('customEvent', console.log);
target.dispatchEvent(new Event('customEvent'));
Run Code Online (Sandbox Code Playgroud)

这提供了您习惯于使用 DOM 事件的所有功能,并且不需要创建空的文档元素或节点。

有关更多信息,请参阅 Mozilla 开发人员指南:https : //developer.mozilla.org/en-US/docs/Web/API/EventTarget

  • 感谢您提供如此优雅的解决方案!这应该是公认的答案。 (4认同)

Jor*_*man 12

Necroposting在这里做了一点,但我昨晚刚刚写了这样的东西 - 超级简单,基于Backbone.js Events模块:

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);
        });
    }
};
Run Code Online (Sandbox Code Playgroud)

这种方法非常简单和可扩展,允许您根据需要在其上构建更复杂的事件系统.

使用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);
}
Run Code Online (Sandbox Code Playgroud)

使用一些简单的命名空间,您将能够轻松地在模块之间传递基本事件!

  • 您可能还需要一个`off`方法来删除事件侦听器 (3认同)

Phi*_*nin 5

您可以使用 JQuery 来完成。

订阅您的自定义事件:

$(computer.keyboard).on('keyEscape', function(e){
    //Handler code
});
Run Code Online (Sandbox Code Playgroud)

用于抛出您的自定义事件:

$(computer.keyboard).trigger('keyEscape', {keyCode:'Blah blah'});
Run Code Online (Sandbox Code Playgroud)

可能不是最好的方法,但您也可以在您的方法中创建函数(addEventListener、dispatchEvent...)来包装 JQuery 逻辑,以支持本机外观的 api 和 JQuery。