PostMessage使用
跨域的问题有一种postMessage的解决方案,之前也一直是听过但是没有用过。
用法
- 发送消息:otherWindow.postMessage(message, targetOrigin, [transfer]);
- 接收消息:window.addEventListener(“message”, (event)=>{}, false);
- postMessage方法的入参:
- message:要发送的数据
- targetOrigin:数据接收方。设置为’*‘,则不限制。不建议这么设置。
- transfer:可选参数。是一串和message 同时传递的 Transferable 对象.这些对象的所有权将被转移给消息的接收方,而发送一方将不再保有所有权。
- event对象的几个属性:
- data:从其他窗口发送过来的消息对象
- type:发型消息的类型
- source:发送消息的窗口对象
- origin:发送消息的窗口的源
举个栗子🌰
下面的写了一个小demo,page one (http://10.161.114.80:8080/index.html/#/test) 和page two (http://10.161.114.80:8082/index.html/#/test)。
- page one在mounted的时候,新打开了一个窗口,然后8秒后了一条消息给page two;
- page one在mounted的时候,监听postMessage回来的消息;并判断如果当前发消息的窗口对象,不是当前窗口对象(window)的话,就发送一条消息给page two。
- page two在mounted的时候,监听postMessage回来的消息。
- page two在mounted的时候,发送一个消息给page one。
//page one
<template>
<div>
<h3>page one</h3>
<input v-model="message" placeholder="edit me" />
<button @click="handleClick">sendMessage</button>
</div>
</template>
<script>
export default {
data() {
return {
message: "",
popup: null
};
},
methods: {
/**
* 打开新窗口
*/
openWindow() {
this.popup = window.open(
"http://10.161.114.80:8082/index.html/#/test",
"title"
);
setTimeout(()=>{
this.sendMess("Hello World!");
},8000)
},
/**
* 使用postMessage发送消息
*/
sendMess(message) {
this.popup.postMessage(
message,
"http://10.161.114.80:8082/index.html/#/test"
);
},
/**
* 点击按钮 发送消息
*/
handleClick() {
if (!this.message) return;
this.sendMess(this.message);
},
/**
* 接收消息
*/
receiveMess() {
window.addEventListener(
"message",
function(e) {
console.log(e);
if (e.source != window) {
// 如果当前source不是window(当前窗口)的话,再发送一条消息出去
e.source.postMessage(
"hello cc",
"http://10.161.114.80:8082/index.html/#/test"
);
}
},
false
);
}
},
mounted() {
this.openWindow();
this.receiveMess();
}
};
</script>
//page two
<template>
<div>
<h3>page two</h3>
<input v-model="message" placeholder="edit me" />
<button @click="handleClick">sendMessage</button>
</div>
</template>
<script>
export default {
data() {
return {
message: ""
};
},
methods: {
/**
* 点击按钮 发送消息
*/
handleClick(message) {
if (!this.message) return;
this.sendMess(this.message);
},
/**
* 使用postMessage发送消息
*/
sendMess(message) {
window.opener.postMessage(
message,
"http://10.161.114.80:8080/index.html/#/test"
);
},
/**
* 接收消息
*/
receive() {
window.addEventListener(
"message",
function(e) {
console.log(e.data);
},
false
);
}
},
mounted() {
this.receive();
this.sendMess("Nice to see you");
}
};
</script>
postMessage的应用场景
最近在看之前同事留下来的代码,其中有一个功能大量用到postMessage。
postMessage常用于两个页面之间通讯。或者页面中引入了iframe,想让当前页面和iframe窗口页面进行通讯。可以使用postMessage。应用场景就是,一般不依赖后台服务,就单纯的前端页面之间的交互。
!!!注意事项
- 直接在浏览器中打开A和B两个页面,之间是无法使用postMessage通讯的。符合通讯的有两种情况:
- 情况一:必须其中一个页面是另一个页面通过window.open()打开的;
- 情况二:A、B两个页面是页面嵌套iframe的关系。可以在iframe的load事件回调中发送请求。
- 监听message事件的时候需要对event.origin进行过滤。