How to propagate event? InvalidStateError: Failed to execute 'dispatchEvent' on 'EventTarget': The event is already being dispatched

时间:2016-04-04 16:50:46

标签: javascript events reactjs

I'm trying to propagate an event from my window.document to an iframe within this document.

When catching the event in the window.document I try the following:

event.preventDefault()
(@dispatchTo()).dispatchEvent(event)
# @dispatchTo() returns the reference of `document.querySelector('iframe').contentDocument`

But I get InvalidStateError: Failed to execute 'dispatchEvent' on 'EventTarget': The event is already being dispatched.

I tried preventDefault and stopPropagation but none would work. It seems that the event is being dispatched while I try to dispatch it to the iframe document and it fails.

How can I propagate an event to my iframe while catching it from the window.document?

I do have another eventListener on the iframe for that event, but it doesn't get triggered.

I use React (which has a virtual DOM, it may interfere, it may not, just saying).


I found part-of-a-solution there: https://stackoverflow.com/a/20541207/2391795

And now I'm able to dispatch events from the document to the iframe using this code:

eventClone = new event.constructor(event.type, event)
(@dispatchTo()).dispatchEvent(eventClone)

But since I'm using React, the cloned event isn't equal to the initial event, because React has a kind-of wrapper for events. So I loose many properties, like the which and isTrusted, which become false once cloned.

Is there any way to properly clone a React event?

1 个答案:

答案 0 :(得分:0)

当您尝试复制事件时,某些事件属性值会消失。这是因为许多事件属性的可枚举属性都设置为false:

Object.defineProperty(event, "target", {
    enumerable: false,
    writable: true,
});

这样可以防止在克隆事件时复制属性的值。如果您尝试过Object.keys(evt),则唯一返回的密钥是isTrusted

某些属性(例如target和path)仅在分派事件之后设置,并且您无法手动分配它们。因此,如果您尝试调度已经具有目标的事件,则会遇到错误InvalidStateError: Failed to execute 'dispatchEvent' on 'EventTarget': The event is already being dispatched

这就是为什么您遇到此错误的原因。您尝试调度一个已经调度的事件,而不是调度一个新事件。

因此,当您创建活动时,只应复制您关心的属性:

 eventClone = new event.constructor(event.type, propertiesICareAbout) 

其中propertiesICareAbout是一个对象,其中包含您关心的事件的各个部分,例如propertiesICareAbout = {shiftKey: event.shiftKey}

isTrusted是具有特定用途的属性-如果脚本与事件进行了交互,则返回false。正是由于这个原因,该属性设置为false。您正在使用脚本与事件进行交互,并通过脚本进行调度。 https://developer.mozilla.org/en-US/docs/Web/API/Event/isTrusted

which属性已被弃用,并且正在被删除,因此无论如何您都不应使用该属性。

反应事件可能与您的问题无关。由于性能原因,React合成事件在顶级被委派和合并。如果要手动调度事件,则应使用本机浏览器方法dispatchEvent