如何在Javascript中向非dom元素添加EventListener?

如何在Javascript中向非dom元素添加EventListener?,javascript,dom-events,Javascript,Dom Events,在Java、C#、Actionscript等中,事件是用于类的,而在Javascript中,事件似乎仅限于dom。我在这里读了一个使用jQuery的示例 但是如果我不需要jQuery,如果我想了解这个机制,你会怎么做?最简单的机制是: function PubSub() { this.subs = {}; this.subscribe = function(channel, sub) { this.subs[channel] = this.subs[channe

在Java、C#、Actionscript等中,事件是用于类的,而在Javascript中,事件似乎仅限于dom。我在这里读了一个使用jQuery的示例


但是如果我不需要jQuery,如果我想了解这个机制,你会怎么做?

最简单的机制是:

function PubSub() {
    this.subs = {};
    this.subscribe = function(channel, sub) {
        this.subs[channel] = this.subs[channel] || []; //create array for channel
        this.subs[channel].push(sub);
    };
    this.publish = function(channel) {
        var args = [].slice.call(arguments, 1); //pop off channel argument
        this.subs[channel].forEach(function(sub) {
            sub.apply(void 0, args); //call each method listening on the channel
        });
    };
}
此处演示:

--编辑(大约5年后)--

相同的简单机制,更新的语法

class PubSub {
    constructor () {
        this.subs = {}
    }
    subscribe (channel, sub) {
        this.subs[channel] = this.subs[channel] || []
        this.subs[channel].push(sub)
    }
    publish (channel, ...args) {
        ;(this.subs[channel] || []).forEach(sub => sub(...args))
    }
}

至少有两种方法可以实现这一点:

--如果您是JQuery用户(目前我不是),可以用JQuery包装简单的JavaScript对象,然后像DOM元素一样,它可以侦听事件。此方法已具有一个。我不确定这种方法在幕后是如何工作的,我计划稍后再调查,你可以自己调查

--使用VanillaJS,您可以通过创建一个事件“类”来实现相同的效果,所有愿意交互的对象都将从该类派生/创建。然后该类的所有实例都将能够注册、发出和广播事件。借用domapi和AngularJS的语义,我编写了一个示例,演示了如何做到这一点以及如何使用它。这是:

/**
*EventfulObject构造函数/基。
*@type EventfulObject_L7.EventfulObjectConstructor|函数
*/
var EventfulObject=函数(){
/**
*从事件名称映射到订阅服务器列表。
*@type对象
*/
var事件={};
/**
*EventfulObject类型的所有实例的列表。
*@type数组
*/
var实例=[];
/**
*@返回{EventfulObject_L1.EventfulObjectConstructor}一个`EventfulObject`。
*/
var EventfulObjectConstructor=函数(){
实例。推(这个);
};
EventfulObjectConstructor.prototype={
/**
*广播给定名称的事件。
*所有希望接收广播的实例都必须实现“receiveBroadcast”方法,正在广播的事件将传递给该实现。
*@param{String}name事件名称。
*@returns{undefined}
*/
广播:功能(名称){
forEach(函数(实例){
(instance.hasOwnProperty(“receiveBroadcast”)&typeof实例[“receiveBroadcast”]=“function”)&&
实例[“接收广播”](名称);
});
},
/**
*仅向订阅了给定名称的实例发出该事件。
*@param{String}name事件名称。
*@returns{undefined}
*/
emit:函数(名称){
event.hasOwnProperty(名称)和&event[name].forEach(函数(订阅){
subscription.process.call(subscription.context);
});
},
/**
*将给定操作注册为命名事件的侦听器。
*此方法将首先创建一个由给定名称标识的事件(如果还不存在)。
*@param{String}name事件名称。
*@param{Function}操作侦听器。
*@返回{Function}此侦听器的注销函数。
*/
on:函数(名称、操作){
event.hasOwnProperty(名称)| |(事件[名称]=[]);
事件[名称]。推送({
背景:这,,
过程:行动
});
var subscriptionIndex=event[name].length-1;
返回函数(){
事件[名称]。拼接(subscriptionIndex,1);
};
}
};
返回EventfulObjectConstructor;
}();
变量模型=函数(id){
调用(this);
this.id=id;
this.receiveBroadcast=函数(名称){
log(“我闻到另一个“+name+”,我是模特“+this.id”);
};
};
Model.prototype=Object.create(EventfulObject.prototype);
Model.prototype.constructor=模型;
//------测试和使用(希望足够清楚…)
//------------注意:我没有测试事件注销。
var ob1=新的EventfulObject();
ob1.on(“垃圾”,函数(){
log(“在广播中说废话?-别把我算在内!”);
});
var模型1=新模型(1);
var模型2=新模型(2);
模型2.关于(“半身像”,函数(){
log(“我是model2,我正在崩溃!”);
});
var ob2=新的EventfulObject();
ob2.on(“半身像”,函数(){
log(“我是ob2-busted!!!”;
});
ob2.receiveBroadcast=函数(){
log(“如果它拉拉链,我会抓住它。-那是我的ob2。”);
};
console.log(“开始:广播\n----------------”;
模式1.广播(“垃圾”);
console.log(“end:BROADCAST\n--------------\n-\n”);
console.log(“开始:发射\n---------------------------”;
ob1.发射(“胸围”);
log(“end:EMIT\n----------------”
代码在JavaScript窗格中!

而且。。。节目就在你的控制台上你到底想做什么?那么一个经典的
Observer
实现呢?您可能想要一个@Thai,您应该扩展您的注释并添加它作为问题的答案。