背景
最近参与的一个Vue项目要改造,原本是普通管理后台项目,现在因为有业务扩展需求(实际上就是一个新的项目,但是要基于现有的UI、权限以及用户等功能,只是一部分业务不一样,两个项目必须要是同一个入口),要把菜单和头部以及一部分公共业务(比如用户、日志、权限、登录等等)拿出来新开一个项目,把原有的业务迁到另一个项目,当然,新的业务也会新开一个项目。
说白了就是三个项目合成一个(Ps:缝合怪),项目入口理所当然是公共的那一部分,业务展示区域采用了iframe展示的方案,具体方式是参考了 Layui Admin(iframe版本)的做法。
既然在Vue项目里用了iframe,而且还是管理后台项目,就没办法避开通信问题了。。。
使用postMessage和onmessage来实现通信
上代码!
父级组件:Home.vue
mounted () {
// 监听并接收User(iframe)发来的信息
window.onmessage = ({data: { type, params }}) => {
switch (type) {
case 'message':
// 调用Message组件
// console.log(params.msg)
break;
case 'dialog':
// 调用Dialog组件
break;
default:
break;
}
}
},
methods: {
// 向User(iframe)内部发送信息
handleSendMessage() {
const iframeWindow = this.$refs.iframe.contentWindow
iframeWindow.postMessage({
// ... 这里是要发过去的数据
}, '*') // 这个'*'就不多说了,大概就是用来做验证的
}
}
iframe承载的子组件: User.vue
<el-button @click="handleSendMessage('message')">发送消息给Home</el-button>
mounted () {
// 监听并接收Home发来的信息
window.onmessage = (e) => {
console.log(e)
// ...
}
},
methods: {
// 向父页面发送信息
handleSendMessage(type) {
const iframeWindow = this.$refs.iframe.contentWindow
iframeWindow.postMessage({
type,
params: {
msg: '这是一条提示信息'
}
}, '*')
}
}
OK,这样就可以了!
最后
可能有的同学就要问了,为啥不用window.addEventListener
来监听接收消息呢,其实也是可以的,但是我遇到一些问题,以下~
window.addEventListener(‘message’, this.handleAcceptMessage)
这个本身是没什么问题的,但是我发现它接收到消息后会多次调用handleAcceptMessage
这个方法,解决办法是绑定this
,window.addEventListener(‘message’, this.handleAcceptMessage)
这样就可以了,大家随意咯~