Vue3 + TypeScript 实现 iframe 嵌入与通信的完整指南以及全屏弹窗方案

创建一个 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 内置弹框全屏问题解决方案

  1. iframe 宽高设置全屏,背景透明,border 设为 0,position 设置为 absolute top,left 设为0。
  2. 内嵌的 html 页面添加padding限制实际展示大小(具体值可由父级传到子级)。
  3. 内嵌页面 bodypadding。
  4. 监听内嵌页面的鼠标移动事件,和父级鼠标移动事件,判断鼠标位置确定用户操作范围,动态修改 iframe 范围外的其他元素层级,以便鼠标点击。
相关推荐
于慨8 小时前
Lambda 表达式、方法引用(Method Reference)语法
java·前端·servlet
石小石Orz8 小时前
油猴脚本实现生产环境加载本地qiankun子应用
前端·架构
从前慢丶8 小时前
前端交互规范(Web 端)
前端
@yanyu6669 小时前
07-引入element布局及spring boot完善后端
javascript·vue.js·spring boot
CHU7290359 小时前
便捷约玩,沉浸推理:线上剧本杀APP功能版块设计详解
前端·小程序
GISer_Jing9 小时前
Page-agent MCP结构
前端·人工智能
王霸天9 小时前
💥别再抄网上的Scale缩放代码了!50行源码教你写一个永不翻车的大屏适配
前端·vue.js·数据可视化
小领航9 小时前
用 Three.js + Vue 3 打造炫酷的 3D 行政地图可视化组件
前端·github
@大迁世界9 小时前
2026年React大洗牌:React Hooks 将迎来重大升级
前端·javascript·react.js·前端框架·ecmascript
PieroPc9 小时前
一个功能强大的 Web 端标签设计和打印工具,支持服务器端直接打印到局域网打印机。Fastapi + html
前端·html·fastapi