跨頁(yè)面通信實(shí)現(xiàn)方案

同源頁(yè)面

廣播模式,頁(yè)面將消息通知給一個(gè)中轉(zhuǎn),中轉(zhuǎn)再通知給各個(gè)頁(yè)面。中轉(zhuǎn)可以是一個(gè) BroadCast Channel 實(shí)例、一個(gè) Service Worker 或是 LocalStorage。

BrocastChannel

BrocastChannel可以實(shí)現(xiàn)同源下瀏覽器不同窗口,tab頁(yè),frame或frame下的瀏覽器上下文之間的通信。

// a頁(yè)面
var bc = new BroadcastChannel('qwer')
bc.postMessage('發(fā)送數(shù)據(jù)')

// b頁(yè)面
var bc = new BroadcastChannel('qwer')
bc.onmessage = function(e) {
  console.log(e)
}
/** 消息發(fā)送后,所有連接到該頻道的 BrocastChannel對(duì)象上都會(huì)觸發(fā) meaasge事件,
該事件沒有默認(rèn)行為,可以使用`onmessage`事件處理程序來定義一個(gè)函數(shù)處理消息
**/

LocalStorage

LocalStorage是前端常用的本地存儲(chǔ),當(dāng)LocalStorage變化是,會(huì)觸發(fā)storage事件,發(fā)送消息時(shí),將消息寫入LocalStorage中,然后在各個(gè)頁(yè)面中,通過監(jiān)聽storage事件即可收到通知。

// a頁(yè)面
window.addEventListener('storage', function(e) {
  console.log(e)
})

// b頁(yè)面
localStorage.setItem('qwer', 10000)

Service Worker

Service Worker與頁(yè)面通信
前端跨頁(yè)面通信的方法

共享存儲(chǔ) + 長(zhǎng)輪詢模式

SharedWorker

SharedWorker可以開啟后臺(tái)線程運(yùn)行腳本,并且多個(gè)頁(yè)面之間可以共享,通過port.postMessage發(fā)送消息,通過監(jiān)聽message事件實(shí)現(xiàn)。如果a頁(yè)面向后臺(tái)線程發(fā)送消息,后臺(tái)線程觸發(fā)message事件后再發(fā)送的消息只能被a頁(yè)面接收,即SharedWorker可以一個(gè)線程處理不同的頁(yè)面邏輯,然后將結(jié)果返回對(duì)應(yīng)的頁(yè)面。

  • 根據(jù)以上原理,在SharedWorker腳本中設(shè)置共享數(shù)據(jù)以實(shí)現(xiàn)頁(yè)面間的通信
//可以在chrome://inspect中對(duì)子線程中的代碼進(jìn)行調(diào)試
onconnect = function(e) {
  console.log(e)
  const port = e.ports[0]
  port.onmessage = function(event){
    console.log(event)
    port.postMessage(event.data)
  }
}

頁(yè)面1中的代碼

var sharedWorker = new SharedWorker('./shareWorker.js', 'cpc')
sharedWorker.port.postMessage({
  a: 1,
  b: 2
})
 // 發(fā)送數(shù)據(jù),此時(shí)共享數(shù)據(jù)的值已經(jīng)被更改

頁(yè)面2中的代碼

var sharedWorker = new SharedWorker('./shareWorker.js', 'cpc')
sharedWorker.port.postMessage({ get: true })

// 如果需要實(shí)時(shí)更新的話,可能需要`setInterval`進(jìn)行輪詢

indexDB方案

前端跨頁(yè)面通信方法

非同源頁(yè)面

非同源頁(yè)面之間的通信通過iframe實(shí)現(xiàn)。各個(gè)需要通信的頁(yè)面加載應(yīng)該相同的iframe,這些iframe之間使用的是同一個(gè)url,屬于同源,可以相互通信,接收到消息后postMessage到主頁(yè)面即可。

// iframe中的代碼
const bc = new BroadcastChannel('cpc')
window.addEventListener('message', function(e) {
  console.log(e)
  if(e.origin === 'https://magazine.heytapimage.com' || e.origin === 'https://magazine-static-cpc.heytapimage.com') {
    bc.postMessage(e.data)
    console.log('bc postMessage')
  }
})
bc.onmessage = function(e) {
  window.parent.postMessage(e.data, 'https://magazine.heytapimage.com') //  支持傳入指定域名或*
  console.log('bc receiveMessage')
}

a頁(yè)面的代碼

<iframe src="https://dhfs-test-cpc.wanyol.com/iframe.html"></iframe>
<script>
  window.frames[0].window.postMessage({
    atob: true,
    numb: 11,
    desc: 'a頁(yè)面向b頁(yè)面發(fā)送的數(shù)據(jù)'
  }, 'https://dhfs-test-cpc.wanyol.com');
</script>

b頁(yè)面的代碼

<iframe src="https://dhfs-test-cpc.wanyol.com/iframe.html"></iframe>
<script>
  window.addEventListener('message', function (e) {
    console.log('b頁(yè)面接收到數(shù)據(jù)')
    if(e.data.atob) {
      console.log(e.data)
    }
  });
</script>
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。