vue组件渲染到iframe里面(同域名下),组件可以在同一项目下维护
思路
- 通过iframe的load事件确保DOM就绪后操作
- 动态写入完整的HTML文档结构
- 在iframe内部创建独立的Vue实例
- 使用render函数动态渲染传入的组件
ParentComponent.vue
<template><div><iframe-renderer :component="embeddedComponent" :propsData="{ message: 'Hello from parent' }"/></div>
</template><script>
import IframeRenderer from './IframeRenderer.vue'
import EmbeddedComponent from './EmbeddedComponent.vue'export default {components: {IframeRenderer,embeddedComponent: EmbeddedComponent}
}
</script>
IframeRenderer.vue
<template><div><iframe ref="iframe" @load="onIframeLoad"></iframe></div>
</template><script>
export default {props: {component: {type: Object,required: true},propsData: {type: Object,default: () => ({})}},methods: {onIframeLoad() {const iframeDoc = this.$refs.iframe.contentDocument// 创建基础HTML结构iframeDoc.open()iframeDoc.write(`<!DOCTYPE html><html><head><title>Embedded Vue Component</title><link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"></head><body><div id="app"></div><script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"><\/script><script src="https://unpkg.com/element-ui/lib/index.js"><\/script></body></html>`)iframeDoc.close()// 在iframe中初始化Vue实例,const iframeWindow = this.$refs.iframe.contentWindownew iframeWindow.Vue({el: iframeDoc.getElementById('app'),render: h => h(this.component, { props: this.propsData })})}}
}
</script>
注意事项
- 需要处理跨域限制(建议同源部署)
- 样式和需单独注入或使用CDN引入
- 组件通信推荐使用postMessage API,不一定耶可以直接调用window下面的函数来实现单向通讯
- 适用于需要沙箱隔离的场景
优点
1.不需要开启单独服务维护iframe里面的html
2.完美支持display:fixed布局问题
疑问?
传过来的不是vue模板吗,怎么可以直接用?
其实打包后传过来就是一个普通js对象了,不影响使用的