如何 send/dispatch 按键事件到 React 中的嵌入式 iframe?
How to send/dispatch keypress events to an embedded iframe in React?
我有一个包含 Google 个幻灯片的 iframe,我将其嵌入到我的网络应用程序中。
iframe 实现是:
<iframe ref={slidesRef} src={src} width='100%' height='100%' allowFullScreen={true}/>
我想监听主网页的点击事件(而iframe不一定是focus),然后创建它们对应的按键事件-并将它们传递给iframe,从而使幻灯片iframe触发和对用户按键做出反应。
我试过这样的事情:
function onButtonClick(e) {
e.stopPropagation();
slidesRef.current.focus();
slidesRef.current.dispatchEvent(new KeyboardEvent('keypress', {
key: 'ArrowRight', which : 39
}));
}
但它不起作用 - 它只关注 iframe,但不发送箭头键事件。
我看到一些解决方案使用 iframe 内的父文档或使用 postMessage
发送消息,但我无法在 iframe 内添加任何代码,因为它的来源是外部 link.
由于所有现代浏览器实施的 Same Origin Policy 所施加的限制,我认为您无法执行您想要执行的操作 - 这与 React 无关,浏览器会只是不允许父 window 上的脚本以编程方式触发子 iframe
上的任何类型 DOM 事件。
这就是为什么您在搜索解决方案时看到对 postMessage
API 的引用。引入 API 是为了以更安全、更可控的方式实现 window 对象之间的跨域通信。
您发布的代码将执行可能附加到父 window 的 DOM iframe 元素的任何事件侦听器,因此如下所示:
<iframe onkeydown="console.log('keydow')" src="https://google/..." />
应该由您的代码触发。但这发生在父 window 上,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
window 被浏览器认为具有“同源”时才有效(这不是你的情况).
尽管要复杂得多,但您可能会通过使用相应的 Google API.
查看相应的文档:https://developers.google.com/slides/quickstart/javascript
一开始可能看起来很可怕,但是一旦你习惯了,Google API就不会那么咬人了,你甚至可以创建一个服务帐户并授予它访问您的文档,以便您的应用程序可以读取文档并更新文档,而无需请求用户授权您的应用程序。
我有一个包含 Google 个幻灯片的 iframe,我将其嵌入到我的网络应用程序中。
iframe 实现是:
<iframe ref={slidesRef} src={src} width='100%' height='100%' allowFullScreen={true}/>
我想监听主网页的点击事件(而iframe不一定是focus),然后创建它们对应的按键事件-并将它们传递给iframe,从而使幻灯片iframe触发和对用户按键做出反应。
我试过这样的事情:
function onButtonClick(e) {
e.stopPropagation();
slidesRef.current.focus();
slidesRef.current.dispatchEvent(new KeyboardEvent('keypress', {
key: 'ArrowRight', which : 39
}));
}
但它不起作用 - 它只关注 iframe,但不发送箭头键事件。
我看到一些解决方案使用 iframe 内的父文档或使用 postMessage
发送消息,但我无法在 iframe 内添加任何代码,因为它的来源是外部 link.
由于所有现代浏览器实施的 Same Origin Policy 所施加的限制,我认为您无法执行您想要执行的操作 - 这与 React 无关,浏览器会只是不允许父 window 上的脚本以编程方式触发子 iframe
上的任何类型 DOM 事件。
这就是为什么您在搜索解决方案时看到对 postMessage
API 的引用。引入 API 是为了以更安全、更可控的方式实现 window 对象之间的跨域通信。
您发布的代码将执行可能附加到父 window 的 DOM iframe 元素的任何事件侦听器,因此如下所示:
<iframe onkeydown="console.log('keydow')" src="https://google/..." />
应该由您的代码触发。但这发生在父 window 上,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
window 被浏览器认为具有“同源”时才有效(这不是你的情况).
尽管要复杂得多,但您可能会通过使用相应的 Google API.
查看相应的文档:https://developers.google.com/slides/quickstart/javascript
一开始可能看起来很可怕,但是一旦你习惯了,Google API就不会那么咬人了,你甚至可以创建一个服务帐户并授予它访问您的文档,以便您的应用程序可以读取文档并更新文档,而无需请求用户授权您的应用程序。