Contents

Iframe跨域通信

iframe间跨域通信

在 web 开发中,使用 iframe 进行通信是一种常见的技术,特别是在需要在页面中嵌入另一个页面或者来自不同域的内容时。通过 iframe 通信,父页面(包含 iframe 的页面)可以与 iframe 内的页面进行交互,以实现一些功能,比如传递数据、调用方法等。

https://gitee.com/plumliil/images/raw/master/Md-2024/1714116025163iframe%E8%B7%A8%E5%9F%9F%E9%80%9A%E4%BF%A1.png

接下来介绍下 PostMessage API + window.parent 来实现iframe父子之间信息传递,在此处父项目为vue3项目,iframe所在项目为react

父:

import { useState } from 'react';
import './App.css'

function App() {
  const [data, setData] = useState({ source: '', msg: '', rm: 0 })
  const clickHandle = () => {
    window.parent.postMessage({ source: 'iframe', msg: 'message From iframe', rm: Math.random().toFixed(2) }, '*');
  }
  //回调函数
  function receiveMessageFromIndex(event: any) {
    setData(event.data)
    console.log('event', event.data);
  }
  //监听message事件
  window.addEventListener("message", receiveMessageFromIndex, false);
  return (
    <>
      <button onClick={clickHandle}>子传父</button>
      <h1>父数据:source: '{data.source}', msg: '{data.msg}', rm: {data.rm}</h1>
    </>
  )
}
export default App

子:

<script setup lang='ts'>
import { onMounted, ref } from 'vue';
const iframeRef = ref<any>()
const iDom = ref<HTMLElement>()
const iframeData = ref<any>({source: '', msg: '', rm: 0})
onMounted(() => {
  const iframeDom = document.getElementById('iframe')
  if (iframeDom)
    iDom.value = iframeDom
  if (!iframeDom) return
  // iframeDom.onload = function () {
  //   //iframe加载完立即发送一条消息
  //   iframeDom.contentWindow.postMessage({ source: 'parent', msg: 'message From Parent' }, '*');
  // }
})
window.addEventListener("message", (e) => {
  console.log('parent window listener', e.data);
  iframeData.value = e.data
}, false);
const clickHandle = () => {
  console.log('iframeRef', iframeRef.value.contentWindow, iDom);
  if (iDom.value)
    iDom.value.contentWindow.postMessage({ source: 'parent', msg: 'message From Parent', rm: Math.random().toFixed(2) }, '*');
}
</script>

<template>
  <iframe ref="iframeRef" id="iframe" src="http://127.0.0.1:5173/" style="width: 100%;height: 50vh;"
    frameborder="0"></iframe>
  <button @click="clickHandle">父传子</button>
  <h1>子数据 {{ iframeData }}</h1>
</template>

<style scoped></style>

即可实现iframe父子应用之间跨域通信