【问题标题】:How to send/dispatch keypress events to an embedded iframe in React?如何将按键事件发送/调度到 React 中的嵌入式 iframe?
【发布时间】:2021-04-07 01:36:09
【问题描述】:

我有一个嵌入到我的网络应用程序中的 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 中添加任何代码,因为它的来源是外部链接。

【问题讨论】:

    标签: javascript reactjs event-handling dom-events keypress


    【解决方案1】:

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

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

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

    【讨论】:

    • 感谢您的信息。你知道this是否可行?
    【解决方案2】:

    由于所有现代浏览器都实施了Same Origin Policy 施加的限制,我认为你无法做你想做的事情——这与 React 无关,浏览器只是不允许父窗口上的脚本以编程方式触发子窗口iframe 上的任何类型的 DOM 事件。

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

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

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

    应该由您的代码触发。但这发生在父窗口上,iframe 中“运行”的 javascript(即负责更改当前幻灯片的 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()
    }
    

    但同样,这只有在 iframe 和 parent 窗口都被浏览器认为具有“相同来源”的情况下才有效(这不是你的情况)。

    【讨论】:

    • 感谢您的意见。有什么解决方法我可以做(甚至是一个hacky)来实现我的目标?
    • hacky 解决方法是postMessage,在这里不起作用^^
    猜你喜欢
    • 2018-02-13
    • 1970-01-01
    • 1970-01-01
    • 2011-11-27
    • 1970-01-01
    • 1970-01-01
    • 2022-10-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多