如何實現瀏覽器標籤頁之間的通訊

發表於2023-09-23

瀏覽器標籤頁之間通訊的實現

使用場景

​ 前端開發過程中,總是避免不了要進行前端標籤頁之間的通訊,最經典的例子莫過於音樂播放網站中,當第一次點選播放列表中的歌曲時,它會開啟一個新的標籤頁進行播放,而當在列表中再次點選歌曲播放時,並不會再多開啟一個標籤頁,而是會在剛才新開啟的標籤頁上播放歌曲。

方式方法

這裡跳轉新頁面均使用window.open1方法,這裡稍微說下window.open方法的引數

  • url(可選)
    一個字串,表示要載入的資源的 URL 或路徑。如果指定空字串("")或省略此引數,則會在目標瀏覽上下文中開啟一個空白頁。
  • target(可選)
    一個不含空格的字串,用於指定載入資源的瀏覽上下文的名稱。如果該名稱無法識別現有的上下文,則會建立一個新的上下文,並賦予指定的名稱。還可以使用特殊的 target 關鍵字:_self_blank_parent_top

    該名稱可用作<a><form>元素的target屬性。

  • windowFeatures(可選)
    一個字串,包含以逗號分隔的視窗特性列表,形式為 name=value,布林特性則僅為 name。這些特性包括視窗的預設大小和位置、是否開啟最小彈出視窗等選項。

    在下面的例子中採用audio作為瀏覽上下文的名稱,讓他從始至終只建立一個新的標籤頁

1.使用路由上的query傳參

list.html

const broadCastChannel = new BroadcastChannel('audio')
function showAudio(){
    //方式一:透過query,缺點會重新整理已開啟的頁面,但並沒有同源策略影響
    window.open('/audio.html?name=張三&id=555','audio')
}

audio.html


const app = document.getElementById('app')
const query = new URLSearchParams(window.location.href.split('?')[1])
app.innerText = query.get('name')

優點:每次開啟,audio頁面都會變為當前活動標籤頁

缺點:

  • 每次開啟,audio頁面都會被重新整理,重新載入
  • 如果新開啟的瀏覽上下文不共享相同的源2,則開啟指令碼將無法與瀏覽上下文的內容進行互動(讀取或寫入)。

2.使用localStroage監聽

利用同源頁面2共享localStroage的特性,利用windw.addEventLister監聽stroage3的變化,來實現兩個標籤頁的通訊,詳細檢視下面例子:

list.html


function showAudio(){
    if(!localStorage.getItem('hasAudio')){
        window.open('/audio.html','audio')
        localStorage.setItem('hasAudio',1)
    }
    setTimeout(()=>{
        localStorage.setItem('name','李四')
    },3000)
}

audio.html

window.onunload = () =>{
    localStorage.removeItem('hasAudio')
    localStorage.removeItem('name')
}
const app = document.getElementById('app')
window.addEventListener('stroage',e=>{
    const app = document.getElementById('app')
    app.innerText = e.newValue
})

優點:

  • 第一次開啟,之後再傳參無需重新整理介面重新載入資源

缺點:

  • 開啟頁面的需為同源頁面,localStroage在同源頁面中共享
  • 同源頁面需透過localStroage檢控通訊,控制麻煩,複雜場景使用不方便

3.使用BroadcastChannel

BroadcastChannel 介面代理了一個命名頻道,可以讓指定 origin 下的任意 browsing context 來訂閱它。它允許同源2的不同瀏覽器視窗,Tab 頁,frame 或者 iframe 下的不同文件之間相互通訊。透過觸發一個 message 事件,訊息可以廣播到所有監聽了該頻道的 BroadcastChannel 物件。

list.html

const broadCastChannel = new BroadcastChannel('audio')
function showAudio(){

    if(!localStorage.getItem('hasAudio')){
        window.open('/audio.html','audio')
        localStorage.setItem('hasAudio',1)
    }

    setTimeout(()=>{
        broadCastChannel.postMessage({name:'李四'})
    },3000)

}

audio.html

window.onunload = () =>{
    localStorage.removeItem('hasAudio')
}
const app = document.getElementById('app')
const broadCastChannel = new BroadcastChannel('audio')
broadCastChannel.addEventListener('message',e=>{
    const {name} = e.data
    const app = document.getElementById('app')
    app.innerText = name
})

優點:

  • 第一次開啟,之後再傳參無需重新整理介面重新載入資源
  • 需要共用頻道的頁面,通訊簡單

缺點:

  • 開啟頁面的需為同源頁面2BroadcastChannel只會向命名頻道相同的同源頁面傳送和接收訊息

  1. window.open文件
  2. 同源頁面:即http協議相同且埠號和ip地址相同的網頁
  3. stroage事件文件

相關文章