如何在iframe内嵌入Vue组件 解决src绑定报错及第三方包不生效问题
解决方案
iframe的src属性仅支持传入合法的URL资源地址,无法直接绑定Vue组件名或组件实例,所以直接赋值组件名会触发组件已定义但未使用的ESLint报错,也无法正常渲染目标组件。可以根据你要嵌入的内容类型选择对应方案:
方案1:嵌入路由页面
如果要展示的是有对应路由的页面,直接使用该路由的完整访问路径作为src的值即可,能100%还原页面原有效果:
<template> <el-dialog title="页面预览" width="80%" :visible.sync="dialogVisible"> <iframe :src="iframeSrc" frameborder="0" width="100%" height="600px"></iframe> </el-dialog> </template> <script> export default { data() { return { dialogVisible: false, // hash模式路由带#前缀,history模式直接写路由路径即可 iframeSrc: '/your/target/page/route' } } } </script>
注意:如果路由有权限校验逻辑,要确保iframe请求的路由可以正常通过鉴权,避免跳转到登录页
方案2:嵌入无路由的普通Vue组件
如果要展示的是没有单独路由的通用组件,可以把组件渲染产物手动写入iframe的document中,示例如下:
Vue2 实现示例
<template> <el-dialog title="组件预览" width="80%" :visible.sync="dialogVisible"> <iframe ref="targetIframe" frameborder="0" width="100%" height="600px" @load="initIframeContent"></iframe> </el-dialog> </template> <script> import TargetComp from './TargetComp.vue' import Vue from 'vue' export default { data() { return { dialogVisible: false, compInstance: null } }, methods: { initIframeContent() { const iframe = this.$refs.targetIframe const iframeDoc = iframe.contentDocument || iframe.contentWindow.document // 写入基础HTML结构,可同步引入项目公共样式保证渲染效果一致 iframeDoc.open() iframeDoc.write(` <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <style> * { margin: 0; padding: 0; } html,body { width: 100%; height: 100%; } /* 可把项目公共样式、组件依赖的UI库样式写在这里 */ </style> </head> <body> <div id="iframe-app"></div> </body> </html> `) iframeDoc.close() // 渲染目标组件到iframe内 const CompConstructor = Vue.extend(TargetComp) this.compInstance = new CompConstructor({ // 需要传props的话在这里配置 propsData: { propA: '测试参数' } }).$mount(iframeDoc.querySelector('#iframe-app')) } }, beforeDestroy() { // 销毁组件实例避免内存泄漏 if(this.compInstance) this.compInstance.$destroy() } } </script>
Vue3 实现示例
把组件渲染逻辑替换为createAppAPI即可:
import { createApp } from 'vue' // 省略其他重复逻辑 initIframeContent() { const iframe = this.$refs.targetIframe const iframeDoc = iframe.contentDocument || iframe.contentWindow.document // 写入HTML结构的逻辑和Vue2版本一致 const app = createApp(TargetComp, { propA: '测试参数' // 传props }) app.mount(iframeDoc.querySelector('#iframe-app')) // 销毁时调用app.unmount()即可 }
避坑提示
- 父子页面跨域通信可使用
postMessageAPI实现 - 要保证组件样式和外层项目一致,需把依赖的公共样式同步写入iframe的head标签内
- 不需要引入第三方iframe相关的npm包,原生实现即可满足需求
内容的提问来源于stack exchange,提问作者Yasin Demirkaya
相关产品推荐
相关产品推荐

