窗口之间的通信,如果是不同域的,会受到浏览器的同源策略的限制,这篇文章介绍的postMessage方法可以解决这个问题
postMessage是window的属性,一般用于跨域窗口之间的通信
我们直接从实例中来学这个方法, 这样会理解的更深
我们现在要实现 https://v.qq.com/和https://ke.qq.com之间的通信
在v.qq.com的控制台中输入下面代码,打开ke.qq.com
为新开窗口注册message事件
接下来用postMessage方法给新窗口发送消息
查看新窗口的控制台
根据打印信息,说明新窗口已收到v.qq.com发来的信息
接下来,我们把message事件的回调函数改下,在我们确定收到v.qq.com的信息后,回复'world'
看上面的截图,新窗口确实在收到v.qq.com发来的信息后,回复了World
讲完了基本的用法,接下来说下注意点
1.如果postMessage的第二个参数和调用它的窗口对象的location.origin不一致,信息会发送不出去,只有一致了才发送的出去
我们来测试一下
执行后没回复,并且在ke.qq.com窗口中报错,错误信息就是说target origin的值为‘http://v.qq.com’和 ke的域不一样,导致postMessage执行失败
上述是协议不一致引起的,如果域名,端口号不一致也会造成这个错误
2.postMessage第二个参数可以用*来代替,效果也是一样的,但是不建议这样做,因为又被恶意网站窃取信息的危险,尤其但你发送密码之类敏感信息的时候,一定要明确指定targetOrigin参数,不能用*代替
我们来试下效果
说明也是?的
3.在web worker中也用到了这个方法,但是第二个参数是忽略的
// worker.js
let name = 'yewenjun'
console.log(self)
self.addEventListener('message', (event)=>{
console.log(`${event.data} from ${event.origin}`)
// do something
// ...
self.postMessage('done')
self.close()
})
// main.js
let worker = new Worker('js/worker.js')
worker.postMessage('hello World!')
worker.addEventListener('message', (event)=>{
console.log(`${event.data} from ${event.origin}`)
})
web worker主要用来执行长任务,用新开的worker线程来执行长任务,防止主线程的阻塞