由于web同源策略的限制,当两个页面处于不同的域名,而又需要数据通信时,两页面是无法交互的,这对页面间的信息传递造成了不小的麻烦,经过一系列的尝试,有以下方法可以实现,在此做个记录。
主要实现思路:
A发送信息给B,带有open:true标志,表示B可以接收A传过来的信息;
B接收到信息,发送成功标志给A;
A收到成功标志后,传open:false的标志给B,表示消息通信成功,关闭通信。
代码实现
A页面代码:
const PAGE_DESIGN_URL = 'url' // 域名地址
function onReceiveMessage(design, appMessage){
// 周期发送消息给B页面
const sendMessage = setInterval(() => {
var message = JSON.stringify(appMessage);
design.postMessage(message, PAGE_DESIGN_URL);
}, 1000)
// 接收B页面回调
function receiveMessage(event) {
console.log('接收回调', event.origin , BASE_API)
// BASE_API 为项目域名
//.PAGE_DESIGN_ORIGIN 为B页面的域名
// 判断消息是否来自B页面的域名
if(event.origin !== PAGE_DESIGN_ORIGIN) return
if(event.data){
const message = JSON.parse(event.data)
// 如果成功接收消息,并且返回为200代表页面设计器已接收到消息传送
if(message.statusCode === 200){
// 向B页面发送关闭消息传送标志open:false
design.postMessage(JSON.stringify({open: false}), PAGE_DESIGN_URL);
// 清空定时发送
window.clearInterval(sendMessage)
}
}
}
window.addEventListener("message", receiveMessage, false)
}
const design = window.open(`${PAGE_DESIGN_URL}`, '_blank');
const appMessage = {
open: true, // 打开连接
token: '',
id: '',
... // 需要传给B页面的信息
}
onReceiveMessage(design, appMessage)
B页面代码:
function receiveMessage(event) {
const messageSoure = [
... // 域名白名单,只接收指定域名传过来的数据
]
if(!messageSoure.includes(event.origin)) {
console.log(`该域名${event.origin}不在白名单中,请查看:`, messageSoure)
return
}
if(event.data && (typeof event.data) === 'string'){
// 返回接收信息
event.source.postMessage(
JSON.stringify({
statusCode: 200,
message: "信息接收成功!"
}),
event.origin);
const appMessageInfo = JSON.parse(event.data)
// 打开连接时,刷新页面
if(appMessageInfo.open){
console.log('appMessageInfo', appMessageInfo)
const {token, id, ...} = appMessageInfo
if(id === undefined) return
// 成功时需要执行的代码
}else{
// 关闭事件监听
window.removeEventListener("message", receiveMessage, false)
}
}
}
// 事件监听
if(isAcceptMessage !== undefined && !isAcceptMessage){
window.addEventListener("message", receiveMessage, false)
}