如何将按键事件发送/调度到 React 中的嵌入式 iframe?

IT技术 javascript reactjs event-handling dom-events keypress
2021-05-27 11:16:35

我有一个嵌入在我的网络应用程序中的 Google 幻灯片 iframe。
iframe 的实现是:

<iframe ref={slidesRef} src={src} width='100%' height='100%' allowFullScreen={true}/>

我想听主网页上的点击事件(而 iframe 不一定处于焦点),然后创建它们相应的按键事件 - 并将它们传递给 iframe,从而使幻灯片 iframe 触发并响应用户键按。

我试过这样的事情:

    function onButtonClick(e) {
        e.stopPropagation();
        slidesRef.current.focus();
        slidesRef.current.dispatchEvent(new KeyboardEvent('keypress', {
            key: 'ArrowRight', which : 39
        }));
    }

但它不起作用 - 它只关注 iframe,但不发送箭头键事件。
我看到了一些使用 iframe 中的父文档或使用 发送消息的解决方案postMessage,但我无法在 iframe 中添加任何代码,因为它的来源是外部链接。

2个回答

由于所有现代浏览器实施同源策略施加的限制,我认为您无法做您打算做的事情 - 这与 React 无关,浏览器将不允许脚本以iframe编程方式在子窗口上触发任何类型的 DOM 事件的父窗口

这就是您postMessage在搜索解决方案时看到对API 的引用的原因引入该 API 是为了以更安全、更可控的方式启用窗口对象之间的跨域通信。

您发布的代码将执行任何可能附加到父窗口的 DOM iframe 元素的事件侦听器,如下所示:

<iframe onkeydown="console.log('keydow')" src="https://google/..." />

应该由您的代码触发。但这发生在父窗口上,其中“运行”的 javascript iframe(即负责更改当前幻灯片的 Google 代码)无权访问,也无法“看到”该事件。

如果 iframe 和您的网页都来自同一个域(换句话说,如果它们具有相同的“来源”),我认为您要实现的目标将更多是:

function onButtonClick(e) {
  e.stopPropagation()

  // Note that we're retrieving a DOM element from the iframe's window object,
  // not the parent's one
  const iframeBody = slidesRef.current.contentDocument.body;

  // Get an element on the iframe's document which has an event listener attached
  // to it that changes the current slide
  const sliderEl = iframeBody.querySelector('...')
  sliderEl.click()
}

但同样,这仅在浏览器认为iframeparent窗口具有“相同来源”时才有效(这不是您的情况)。

尽管要复杂得多,但您可能会通过使用相应的 Google API 查询 Google 幻灯片来获得与您正在寻找的内容相近的东西(至少以重建某些网页的设计为代价)。

查看相应的文档:https : //developers.google.com/slides/quickstart/javascript

一开始可能看起来很吓人,但是一旦习惯了,Google API 就不会那么麻烦了,您甚至可以创建一个服务帐户并授予它访问您的文档的权限,以便您的应用程序可以读取文档并进行更新它不要求用户授权您的应用程序。