瀏覽器標籤頁之間通訊的實現
使用場景
前端開發過程中,總是避免不了要進行前端標籤頁之間的通訊,最經典的例子莫過於音樂播放網站中,當第一次點選播放列表中的歌曲時,它會開啟一個新的標籤頁進行播放,而當在列表中再次點選歌曲播放時,並不會再多開啟一個標籤頁,而是會在剛才新開啟的標籤頁上播放歌曲。
方式方法
這裡跳轉新頁面均使用window.open
1方法,這裡稍微說下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
})
優點:
- 第一次開啟,之後再傳參無需重新整理介面重新載入資源
- 需要共用頻道的頁面,通訊簡單
缺點:
- 開啟頁面的需為同源頁面2,
BroadcastChannel
只會向命名頻道相同的同源頁面傳送和接收訊息
- window.open文件 ↩
- 同源頁面:即http協議相同且埠號和ip地址相同的網頁 ↩
- stroage事件文件 ↩