javascript 是否可以在常规对象(不是 DOM 对象)上调度事件?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6635138/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-25 21:21:01  来源:igfitidea点击:

Is it possible to dispatch events on regular objects (not DOM ones)?

javascripteventsdomfilereaderdispatch

提问by jayarjo

I just found out that FileReader dispatches events just as if it was a DOM element. Is it? I wonder if it's possible to create an object similar to FileReader, which doesn't have a representation in HTML/XML structure, but can dispatch events?

我刚刚发现 FileReader 调度事件就像它是一个 DOM 元素。是吗?我想知道是否可以创建一个类似于 FileReader 的对象,它在 HTML/XML 结构中没有表示,但可以调度事件?

回答by bobince

FileReaderhas methods like addEventHandlerbecause it is definedto implement the EventTargetinterface. EventTargetis defined by the DOM Eventsspec but you don't need to be a DOM object to implement it. window, XMLHttpRequestand FileReaderare other Browser Object Model objects that implement EventTarget.

FileReader有类似的方法,addEventHandler因为它被定义为实现EventTarget接口。EventTargetDOM 事件规范定义,但您无需成为 DOM 对象即可实现它。windowXMLHttpRequest并且FileReader是其他实现EventTarget.

Unfortunately there's no easy way to piggyback on the browser's native implementation of event targets... you could try inheriting from a browser object by using one as a prototypeproperty, but that's very unreliable in general. However it is not too difficult to write code to implement all the methods yourself in plain JavaScript:

不幸的是,没有简单的方法可以搭载浏览器的事件目标的本机实现......您可以尝试通过使用一个作为prototype属性从浏览器对象继承,但这通常非常不可靠。然而,用纯 JavaScript 自己编写代码来实现所有方法并不难:

function CustomEventTarget() { this._init(); }

CustomEventTarget.prototype._init= function() {
    this._registrations= {};
};
CustomEventTarget.prototype._getListeners= function(type, useCapture) {
    var captype= (useCapture? '1' : '0')+type;
    if (!(captype in this._registrations))
        this._registrations[captype]= [];
    return this._registrations[captype];
};

CustomEventTarget.prototype.addEventListener= function(type, listener, useCapture) {
    var listeners= this._getListeners(type, useCapture);
    var ix= listeners.indexOf(listener);
    if (ix===-1)
        listeners.push(listener);
};

CustomEventTarget.prototype.removeEventListener= function(type, listener, useCapture) {
    var listeners= this._getListeners(type, useCapture);
    var ix= listeners.indexOf(listener);
    if (ix!==-1)
        listeners.splice(ix, 1);
};

CustomEventTarget.prototype.dispatchEvent= function(evt) {
    var listeners= this._getListeners(evt.type, false).slice();
    for (var i= 0; i<listeners.length; i++)
        listeners[i].call(this, evt);
    return !evt.defaultPrevented;
};

Caution: the above code is off the top of my head and untested, but may work. However it has limitations like only supporting the dispatchEventreturn value if the Eventobject supports the DOM Level 3 defaultPreventedproperty, and no support for DOM Level 3 stopImmediatePropagation()(which is impossible to implement unless you rely on your own Event object that exposes a property for it). Also there's no implementation of hierarchy or capture/bubbling.

注意:上面的代码不在我的脑海中并且未经测试,但可能有效。然而,它有一些限制,比如dispatchEvent如果Event对象支持 DOM Level 3defaultPrevented属性,则仅支持返回值,并且不支持 DOM Level 3 stopImmediatePropagation()(这是不可能实现的,除非您依赖自己的 Event 对象为其公开属性)。也没有层次结构或捕获/冒泡的实现。

So IMO: you don't gain much by trying to write code that participates in the DOM Events model. For plain-JS callback work I'd just go with your own ad hoc implementation of listener-lists.

所以 IMO:通过尝试编写参与 DOM 事件模型的代码,您不会获得太多收益。对于普通的 JS 回调工作,我只会使用您自己的侦听器列表的临时实现。

回答by bsimpson

bobince has the right idea, but his code is just an example. For an actual battle-tested implementation, Mr. Doob has one that he uses in three.js.

bobince 有正确的想法,但他的代码只是一个例子。对于经过实际实战考验的实现,Doob 先生有一个他在 Three.js 中使用的实现

回答by skibulk

jQuery can dispatch events from regular objects. Here's a fiddle.

jQuery 可以从常规对象调度事件。这是一个小提琴

function MyClass() {
    $(this).on("MyEvent", function(event) {
        console.log(event);
    });

    $(this).trigger("MyEvent");
}

var instance = new MyClass();

回答by phtrivier

I assume it's javascript ; normally any object that can get a reference to a DOM element should be able to dispatch an event using the element.dispatchEvent function ; see :

我假设它是 javascript ;通常,任何可以获取 DOM 元素引用的对象都应该能够使用 element.dispatchEvent 函数调度事件;看 :

https://developer.mozilla.org/en/DOM/document.createEvent

https://developer.mozilla.org/en/DOM/document.createEvent

https://developer.mozilla.org/en/DOM/element.dispatchEvent

https://developer.mozilla.org/en/DOM/element.dispatchEvent