创建一个 IframeComponent 组件,用于嵌入 iframe
创建 src/components/IframeComponent.vue 文件:
html
<template>
<div class="iframe-container">
<iframe ref="iframeRef" :src="src" :style="iframeStyle" @load="handleIframeLoad"></iframe>
</div>
</template>
<script lang="ts" setup>
import { ref, onMounted, computed } from 'vue';
const props = defineProps({
src: {
type: String,
required: true,
},
fullscreen: {
type: Boolean,
default: false,
},
});
const iframeRef = ref<HTMLIFrameElement | null>(null);
const iframeStyle = computed(() => ({
width: props.fullscreen ? '100vw' : '600px',
height: props.fullscreen ? '100vh' : '400px',
border: 'none',
}));
const handleIframeLoad = () => {
console.log('Iframe loaded');
};
onMounted(() => {
if (iframeRef.value) {
iframeRef.value.addEventListener('load', handleIframeLoad);
}
});
</script>
<style scoped>
.iframe-container {
position: relative;
overflow: hidden;
}
</style>
实现父子通信
创建 src/components/ParentComponent.vue 文件
html
<template>
<div class="parent-container">
<h1>父组件</h1>
<button @click="sendMessage">向Iframe发送消息</button>
<button @click="toggleFullscreen">切换全屏</button>
<IframeComponent
ref="iframeComponentRef"
:src="iframeSrc"
:fullscreen="isFullscreen"
/>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import IframeComponent from './IframeComponent.vue';
const iframeComponentRef = ref(null);
const iframeSrc = "https://example.com";
const isFullscreen = ref(false);
const sendMessage = () => {
const iframeWindow = iframeComponentRef.value?.iframeRef?.contentWindow;
if (iframeWindow) {
iframeWindow.postMessage("来自父组件的问候", "*");
}
};
const toggleFullscreen = () => {
isFullscreen.value = !isFullscreen.value;
};
</script>
<style scoped>
.parent-container {
padding: 20px;
}
button {
margin-right: 10px;
margin-bottom: 10px;
}
</style>
iframe 接收消息
在 iframe 加载的页面中,需要添加代码来监听来自父页面的消息。
创建 public/iframe.html 文件:
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Iframe页面</title>
<style>
body {
font-family: Arial, sans-serif;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
background-color: #f0f0f0;
}
.message-container {
background-color: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
</style>
</head>
<body>
<div class="message-container">
<h1>Iframe页面</h1>
<p id="message">等待消息...</p>
</div>
<script>
window.addEventListener("message", (event) => {
console.log("收到来自父页面的消息:", event.data);
document.getElementById(
"message"
).textContent = `收到消息: ${event.data}`;
});
</script>
</body>
</html>
使用组件
在 App.vue 中使用创建的 ParentComponent
html
<template>
<div id="app">
<ParentComponent />
</div>
</template>
<script lang="ts" setup>
import ParentComponent from './components/ParentComponent.vue';
</script>
iframe 内置弹框全屏问题解决方案
- iframe 宽高设置全屏,背景透明,border 设为 0,position 设置为 absolute top,left 设为0。
- 内嵌的 html 页面添加padding限制实际展示大小(具体值可由父级传到子级)。
- 内嵌页面 bodypadding。
- 监听内嵌页面的鼠标移动事件,和父级鼠标移动事件,判断鼠标位置确定用户操作范围,动态修改 iframe 范围外的其他元素层级,以便鼠标点击。