一、简介
postMessage是HTML5中新引入的API,它可以实现跨窗口以及跨域的通信。postMessage类似与Ajax但是它不受同源策略的限制并且通信双方都是客户端。本文的目的就是验证下这种跨页面通信方法的使用流程。
二、具体准备
1、首先我们先写一个页面a,页面嵌套一个iframe标签,iframe的地址为b页面
<div id="app" class="page-box">
main-page
<iframe id="iframe" src="http://127.0.0.1:5500/src/html-pages2/iframe-page.html"
frameborder="1"></iframe>
</div>
2、编写a页面发送消息的接口
window.postMessage(message, targetOrigin,[transfer]);
message: 要发送的数据。这个参数可以是任何可以序列化成字符串的JavaScript值,包括字符串、数字、布尔值以及对象(对象会被自动转换为JSON字符串)。
targetOrigin: 一个字符串,指定了接收消息窗口的源(origin)。这个参数是必需的,用来限制哪些源可以接收到消息。如果设置为’*',则表示任何源都可以接收消息,但这不推荐,因为它可能会带来安全风险。
transMessage() {
let otherWindow = document.getElementById('iframe').contentWindow
let message = '来自主页面的消息'
let msgJson = JSON.stringify(message)
otherWindow.postMessage(msgJson, "http://127.0.0.1:5500/src/html-pages2/iframe-page.html")
}
mounted() {
window.addEventListener('message', (event) => {
console.log(event.data)
}, false)
setTimeout(() => {
this.transMessage()
}, 2000)
},
3、b页面 iframe页面,监听message
mounted() {
window.addEventListener('message', this.handleMessage, false)
},
handleMessage(event) {
console.log('message', event.data)
let message = '已收到'
let msgStr = JSON.stringify(message)
parent.postMessage(msgStr, 'http://127.0.0.1:5500/src//html-pages2/index-page.html')
} // parent可以获取父窗口window
window.parent 返回父窗口,如果窗口本身是顶层窗口,parent属性返回的是对自身的引用
window.top 返回顶层窗口,即浏览器窗口,如果窗口本身就是顶层窗口,top属性返回的是对自身的引用
window.self 是对当前窗口自身的引用。它和window属性是等价的。
三、实现代码
全部代码
a页面:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<meta name="referrer" content="origin">
<meta name="viewport" content="width=device-width, viewport-fit=cover, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
<meta name="Cache-Control" content="no-cache, no-store, must-revalidate">
<script type="text/javascript" src="https://cdn.bootcss.com/vConsole/3.3.0/vconsole.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.16"></script>
<script src="./js/flexible.js"></script>
<style>
.page-box {
box-sizing: border-box;
/* background-color: #f2f6ff; */
background-color: #fff;
padding: .36rem;
}
</style>
</head>
<body>
<div id="app" class="page-box">
main-page
<iframe id="iframe" src="http://127.0.0.1:5500/html-pages2/iframe-page.html" frameborder="1"></iframe>
</div>
<script>
let vue = new Vue({
el: '#app',
data() {
return {
order: {}
}
},
mounted() {
window.addEventListener('message', (event) => {
console.log(event.data)
}, false)
setTimeout(() => {
this.transMessage()
}, 2000)
},
methods: {
transMessage() {
let otherWindow = document.getElementById('iframe').contentWindow
let message = '来自主页面的消息'
let msgJson = JSON.stringify(message)
otherWindow.postMessage(msgJson, "http://127.0.0.1:5500/html-pages2/iframe-page.html")
}
}
})
</script>
</body>
</html>
b页面:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<meta name="referrer" content="origin">
<meta name="viewport" content="width=device-width, viewport-fit=cover, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
<meta name="Cache-Control" content="no-cache, no-store, must-revalidate">
<script type="text/javascript" src="https://cdn.bootcss.com/vConsole/3.3.0/vconsole.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.16"></script>
<script src="./js/flexible.js"></script>
<style>
.page-box {
box-sizing: border-box;
/* background-color: #f2f6ff; */
background-color: #fff;
padding: .36rem;
}
</style>
</head>
<body>
<div id="app" class="page-box">
iframe-page
</div>
<script>
let vue = new Vue({
el: '#app',
data() {
return {
order: {}
}
},
mounted() {
window.addEventListener('message', this.handleMessage, false)
},
methods: {
handleMessage(event) {
console.log('message', event.data)
let message = '已收到'
let msgStr = JSON.stringify(message)
parent.postMessage(msgStr, 'http://127.0.0.1:5500/html-pages2/index-page.html')
}
}
})
</script>
</body>
</html>
页面效果:
四、注意事项
因为a页面加载时机比iframe中的b页面加载时机快,所以b页面中的message监听会慢于父页面mounted中的发送消息,这样会接受消息失败,所以加了setTimeout函数来延时发送消息。