父子页面跨域
通过 postMessage
和 window.addEventListener('message', e => { ... })
配合使用,我们就能够完成跨域 iframe 父子页面的通信。
注:对于同源的 iframe 父子页面同样适用。
<iframe
id='iframe'
name='test'
src='http://127.0.0.1:8002/child.html'
frameborder='0'
scrolling='no'>
</iframe>
- 父页面发送信息,子页面接收信息
// http://127.0.0.1:8001/parent.html 父页面发送信息
document.getElementById('iframe').onload = function () {
test.window.postMessage('hello, child!', 'http://127.0.0.1:8002');
}
// http://127.0.0.1:8002/child.html 子页面接收信息
window.addEventListener('message', e => {
// 通过origin对消息进行过滤,避免遭到XSS攻击
if (e.origin === 'http://127.0.0.1:8001') {
console.log(e.origin) // 父页面所在的域
console.log(e.data) // 父页面发送的消息, hello, child!
}
}, false);
- 子发送信息,父接收信息
// http://127.0.0.1:8002/child.html
window.top.postMessage('hello, parent!', 'http://127.0.0.1:8001');
// http://127.0.0.1:8001/parent.html
window.addEventListener('message', e => {
if (e.origin === 'http://127.0.0.1:8002') {
console.log(e.origin) // 子页面所在的域
console.log(e.data) // 子页面发送的消息, hello, parent!
}
}, false);
实例
需求描述:
vue 页面嵌入了一个 iframe 列表页面, 点击列表详情可进入编辑页面, 编辑页里不显示 vue 页面的菜单栏, 而返回到列表页, 需显示菜单栏
思路:
在 iframe 子页面初始化加载和单击返回按钮行为里, 执行
window.top.postMessage('toggleMenu')
;
在父页面加载行为里, 监听到 message 内容为 toggleMenu
时, 就调用 toggleMenu 的方法, 切换菜单栏的显示.
// menu.vue
<template>
<el-menu
router
:default-active="activeIndex"
class="el-menu-demo"
mode="horizontal"
@select="handleSelect"
>
<el-menu-item index="/datasourceManager">推送数据源管理</el-menu-item>
...
</el-menu>
</div>
<router-view @toggleMenu="showMenu = !showMenu" />
</div>
</div>
</template>
data() {
return { activeIndex: '/datasourceManager', showMenu: true, } },
// 父页面 datasourceManager.vue
<iframe
id="push-datasource-area"
ref="iframe"
src="/bdap/bom/fulllinkcata/datamonitor/datasourcemgrList.html"
frameborder="0"
></iframe>
mounted() {
window.addEventListener('message', (e) => {
if (e.data === 'toggleMenu') this.$emit('toggleMenu') })
},
// 子页面
/** * 返回按钮跳转 */
function
backTo(ui) {
// 用于嵌入vue页面显示tab栏
window.top.postMessage('toggleMenu')
...
}
/** * 页面初始化数据加载行为 */
function pageInitBeforeProcess() {
// 用于嵌入vue页面隐藏tab栏
window.top.postMessage('toggleMenu')
...
}