- 本文記錄一下工作中關(guān)于雙標(biāo)簽頁通信問題
- 涉及的技術(shù):
vuewebpackpostMessage iframe - 如今網(wǎng)上已經(jīng)有許多關(guān)于多標(biāo)簽頁通信技術(shù)文檔,但終究不是十分適用自己的需求,所以實踐出真知,我來總結(jié)一下自己的經(jīng)驗
- 了解一下
postMessage:MDN-postMessage
主要是下面2個API
onmessage
window.onmessage = e =>{
console.log(e.data) //接收到的信息在e.data里
}
postMessage
window.postMessage({event:'changePoroject',data:{name:'小強'}},location.origin)
注意點說明:
1.window-指的是需要傳遞消息頁面的引用
2.傳遞的第二個參數(shù)官方說明是-可以接收消息的頁面(一般指url)
iframe
<iframe src='baidu.com' ref='iframe1' id='iframe><iframe>
獲取iframe的window對象
vue
this.$refs.iframe1.contentWindow
-
iframe內(nèi)外傳遞信息也是通過postmesage和postMessage
- 下面來聊一下兩個
Tab頁通信的實現(xiàn)方式和注意點
- 約定數(shù)據(jù)格式-也就是
mesasge選項的格式
{event:'changePoroject',data:{name:'小強'}}
event為我要傳遞的事件,data我要傳遞的參數(shù),這樣就能像監(jiān)聽事件一樣來交互
-
onmessage監(jiān)聽事件-放在mounted或created里 -
window.open打開子頁面- 子頁面初始化(包括初次打開和頁面刷新)時,向父頁面發(fā)送請求,初始化數(shù)據(jù);監(jiān)聽子頁面
onload事件初始化數(shù)據(jù),有時間上的誤差,不能及時初始化子頁面數(shù)據(jù),所以要在mounted或created里向父頁面發(fā)送初始化請求 - 父頁面點擊關(guān)閉和刷新頁面時,子頁面引用對象調(diào)用
close方法,childPage.close() - 監(jiān)聽子頁面關(guān)閉,循環(huán)監(jiān)聽子頁面
closed值,為true則改變父頁面的相關(guān)狀態(tài) - 子頁面監(jiān)聽父頁面的刷新狀態(tài),如果父頁面刷新-關(guān)閉自己-
window.close() - 在子頁面里-
window.opener代表了父頁面,可以使用window.opener.postMessage來向父頁面發(fā)送消息
- 子頁面初始化(包括初次打開和頁面刷新)時,向父頁面發(fā)送請求,初始化數(shù)據(jù);監(jiān)聽子頁面
-
webpack
初始化時,onmessage會監(jiān)聽到webpack發(fā)送的請求,所以接收到數(shù)據(jù)后要先判斷數(shù)據(jù)格式,然后再進行操作
下面是兩個頁面交互的部分代碼
//打開分屏頁面
this.childPage = window.open(this.secondUrl,‘child’)
let loop = setInterval(()=>{
if(this.childPage.closed){
clearInterval(loop)
.... //監(jiān)聽子頁面關(guān)閉,父頁面做出相應(yīng)的改動
}
},1000)
//主頁面
mounted(){
window.onmessage = e => {
if(typeof e.data === 'string'){
console.log('傳遞無效信息')
}else {
if(e.data.event){
console.log('正常發(fā)送數(shù)據(jù)')
swith(e.data.event){
case 'getData':
//子頁面初始化獲取數(shù)據(jù)
}
....//其他事件
}
}
}
}
//向子頁面發(fā)送數(shù)據(jù)
this.childPage.postMessage({event:'initData',data:this.transforData},location.origin)
//子頁面初始化
mounted(){
window.onmessage = e => {
if(typeof e.data === 'string'){
console.log('傳遞無效信息')
}else {
if(e.data.event){
console.log('正常發(fā)送數(shù)據(jù)')
swith(e.data.event){
case 'initData':
this.initial(e.data.data)
//子頁面響應(yīng)父頁面數(shù)據(jù)變化
}
....//其他事件
}
}
}
window.opener.postMessage({event:'getData'})//初始化向父頁面索取數(shù)據(jù)
window.opener.onunload = () => {
window.close()//監(jiān)聽到父頁面關(guān)閉后,子頁面自動關(guān)閉
}
}
下面是每個頁面的iframe交互-兩個頁面間的iframe交互只是需要本頁面監(jiān)聽iframe事件后,向另一個頁面發(fā)送數(shù)據(jù)
<iframe :src='/model/ppt.htm' ref='iframe' id='iframe><iframe>
//向iframe發(fā)送數(shù)據(jù)
this.$refs.iframe.contentWindow.postMessage({event:'onSelectDate',data:this.date},this.$refs.iframe1.src)
//監(jiān)聽iframe的事件也放在mounted的onmessage里
本文正在參加“寫編程博客瓜分千元現(xiàn)金”活動,關(guān)注公眾號“饑人谷”回復(fù)“編程博客”參與活動。