Two primary approaches are available for exchanging data betweeen a parent window and an embedded iframe. The first relies on direct access via contentWindow when both documents share the same origin; the second uses the standard postMessage API to handle cross‑origin scenarios.
1. Communication via contentWindow
- TypeScript declaration file
declare global {
interface Window {
recvFromParent?: (message: string) => void
recvFromChild?: (message: string) => void
}
}
export {}
- Parent window (Vue component)
<template>
<div>
<button @click="transmitToChild">Parent Button</button>
<iframe
style="display: block; width: 100%; height: 600px"
ref="frameEl"
src="/child.html"
frameborder="0"
></iframe>
</div>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue'
export default defineComponent({
setup() {
const frameEl = ref<HTMLIFrameElement>()
const transmitToChild = () => {
// Must be same origin
frameEl.value?.contentWindow?.recvFromParent?.('Parent says hello to child')
}
window.recvFromChild = (message) => {
console.log(message)
}
return {
frameEl,
transmitToChild
}
}
})
</script>
<style lang="scss" scoped></style>
- Child window (plain HTML)
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Child Window</title>
<style>
html, body {
height: 100%;
}
body {
margin: 0;
background: #cccccc;
}
</style>
</head>
<body>
<button onclick="transmitToParent()">Child Button</button>
<script>
window.recvFromParent = (message) => {
console.log(message);
};
function transmitToParent() {
window.parent.recvFromChild?.("Child says hello to parent");
}
</script>
</body>
</html>
2. Communicatino via postMessage
- Parent window (Vue component)
<template>
<div>
<button @click="sendMessageToChild">Parent Button</button>
<iframe
style="display: block; width: 100%; height: 600px"
ref="frameEl"
src="http://localhost:3000"
frameborder="0"
></iframe>
</div>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue'
export default defineComponent({
setup() {
const frameEl = ref<HTMLIFrameElement>()
const sendMessageToChild = () => {
// Works across different origins
frameEl.value?.contentWindow?.postMessage(
{ payload: 'Parent says hello (cross-origin)' },
'*'
)
}
window.addEventListener('message', function (event) {
console.log('Parent received', event)
})
return {
frameEl,
sendMessageToChild
}
}
})
</script>
<style lang="scss" scoped></style>
- Child window (plain HTML)
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Child Window</title>
<style>
html, body {
height: 100%;
}
body {
margin: 0;
background: #cccccc;
}
</style>
</head>
<body>
<button onclick="sendMessageToParent()">Child Button</button>
<script>
window.addEventListener("message", function(event) {
console.log("Child received", event);
});
function sendMessageToParent() {
window.parent.postMessage({ payload: "Child says hello (cross-origin)" }, "*");
}
</script>
</body>
</html>