是否可以在常规对象(而非 DOM 对象)上分派事件?

发布于 2024-11-19 00:30:35 字数 103 浏览 5 评论 0原文

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

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

泪意 2024-11-26 00:30:35

FileReader 具有类似于 addEventHandler 的方法,因为它是定义的 实现 EventTarget 接口。 EventTargetDOM Events 规范定义,但您不这样做不需要是 DOM 对象来实现它。 windowXMLHttpRequestFileReader 是实现 EventTarget 的其他浏览器对象模型对象。

不幸的是,没有简单的方法可以利用浏览器的事件目标本机实现...您可以尝试通过使用浏览器对象作为 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;
};

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

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

FileReader has methods like addEventHandler because it is defined to implement the EventTarget interface. EventTarget is defined by the DOM Events spec but you don't need to be a DOM object to implement it. window, XMLHttpRequest and FileReader are other Browser Object Model objects that implement 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 prototype property, 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:

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 dispatchEvent return value if the Event object supports the DOM Level 3 defaultPrevented property, 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.

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.

染墨丶若流云 2024-11-26 00:30:35

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

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.

早茶月光 2024-11-26 00:30:35

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

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

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

var instance = new MyClass();

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

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

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

var instance = new MyClass();
月依秋水 2024-11-26 00:30:35

我认为它是 javascript ;通常,任何可以获得 DOM 元素引用的对象都应该能够使用 element.dispatchEvent 函数调度事件;请参阅:

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

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

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 :

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

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文