JS中BroadcastChannel實現(xiàn)瀏覽器標簽頁通信
瀏覽器標簽頁通信常用于列表頁進入詳情頁所進行的標簽頁間通信的情況,實際使用例如博客頁面的列表和文章編輯頁面、音樂網站的列表和音樂播放詳情等。
window.open()實現(xiàn)
使用常用的window.open()API也可以實現(xiàn),但會存在以下問題:
- 打開新頁面時瀏覽器標簽頁焦點也會跳轉到新頁面(如果沒有標簽頁焦點不變的需求可以忽略不計);
- 打開新頁面導致新頁面全局刷新(多頁應用或跳轉的新頁面內容較少可忽略不計);
BroadcastChannel實現(xiàn)
BroadcastChannel 是 Web API 里用于在同源的不同瀏覽器上下文(像不同的窗口、標簽頁、iframe 等)間進行通信的機制,因此可以規(guī)避以上兩個問題:
實現(xiàn)過程
創(chuàng)建兩個路由頁面
- 列表頁
/ - 詳情頁
/detail
列表頁
<template>
<div class="table-box">
<el-table :data="tableData" style="width: 100%">
<el-table-column prop="username" label="用戶名" />
<el-table-column prop="sex" label="性別" />
<el-table-column fixed="right" label="操作" min-width="120">
<template #default="scope">
<el-button
link
type="primary"
size="small"
@click="handleClick(scope.row)"
>
詳情
</el-button>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script setup>
import { ref } from "vue";
import { userList } from "@/utils/data";
const handleClick = async (row) => {
// channel通信
const channel = new BroadcastChannel("user_detail");
const tabCount = localStorage.getItem("TAB_COUNT");
if (!tabCount || tabCount === "1") {
await localStorage.setItem("TAB_COUNT", "2");
await sessionStorage.setItem("TAB_ID", row.id);
window.open("/detail", "user_detail");
} else {
channel.postMessage(row.id);
}
};
const tableData = ref(userList);
</script>
詳情頁
<template>
<el-descriptions
class="margin-top"
title="用戶信息表"
:column="3"
size="large"
border
>
<template #extra>
<el-button type="primary" @click="goBack">返回</el-button>
</template>
<el-descriptions-item>
<template #label>
<div class="cell-item">
<el-icon :style="iconStyle">
<user />
</el-icon>
用戶名
</div>
</template>
{{ curUser.username }}
</el-descriptions-item>
<el-descriptions-item>
<template #label>
<div class="cell-item">
<el-icon :style="iconStyle">
<iphone />
</el-icon>
年齡
</div>
</template>
{{ curUser.age }}
</el-descriptions-item>
<el-descriptions-item>
<template #label>
<div class="cell-item">
<el-icon :style="iconStyle">
<location />
</el-icon>
籍貫
</div>
</template>
{{ curUser.city }}
</el-descriptions-item>
<el-descriptions-item>
<template #label>
<div class="cell-item">
<el-icon :style="iconStyle">
<tickets />
</el-icon>
性別
</div>
</template>
{{ curUser.sex }}
</el-descriptions-item>
<el-descriptions-item>
<template #label>
<div class="cell-item">
<el-icon :style="iconStyle">
<office-building />
</el-icon>
住址
</div>
</template>
{{ curUser.address }}
</el-descriptions-item>
</el-descriptions>
</template>
<script setup>
import { ref, onMounted } from "vue";
import { useRoute } from "vue-router";
import { userList } from "@/utils/data";
const route = useRoute();
const initialUser = {
date: "",
username: "",
sex: "",
age: 18,
city: "",
address: "",
id: "",
};
const curUser = ref({ ...initialUser });
const goBack = async () => {
await localStorage.setItem("TAB_COUNT", "1");
await sessionStorage.removeItem("TAB_ID");
window.close();
};
const iconStyle = {
fontSize: "20px",
color: "#409eff",
};
const channel = new BroadcastChannel("user_detail");
channel.addEventListener("message", (event) => {
console.log("接收到消息:", event.data);
sessionStorage.removeItem("TAB_ID");
const curUserId = event.data;
const user = userList.find((user) => user.id === curUserId);
if (user) {
curUser.value = user;
}
});
onMounted(() => {
const curUserId = sessionStorage.getItem("TAB_ID");
if (curUserId) {
const user = userList.find((user) => user.id === curUserId);
if (user) {
curUser.value = user;
}
}
// 監(jiān)聽頁面卸載事件
window.addEventListener("unload", async () => {
await localStorage.setItem("TAB_COUNT", "1");
await sessionStorage.removeItem("TAB_ID");
});
});
</script>
實現(xiàn)效果

實現(xiàn)原理
使用BroadcastChannel創(chuàng)建通道進行瀏覽器標簽頁通信,利用瀏覽器本地緩存記錄標簽頁打開數(shù)量,如果數(shù)量為1(僅有列表頁,沒有詳情頁),則使用window.open打開;反之如果數(shù)量為2,則使用BroadcastChannel通道發(fā)送消息實現(xiàn)頁面數(shù)據(jù)更新;
BroadcastChannel和postMessage區(qū)別
相同點:
- 都可在不同頁面之間,進行信息通訊
不同點:
- BroadcastChannel只可用于同源的不同頁面;
- postmessage可以任何源
1.BroadcastChannel使用方法
// 實例BroadcastChannel
const myChannel = new BroadcastChannel('aa');
// 發(fā)送信息
myChannel.postMessage('發(fā)送的某些數(shù)據(jù)');
myChannel.onmessage = function(e){
// 接收到的消息
console.log(e.data);
}
// 關閉鏈接
myChannel.close();
2.postMessage使用方法
//給其他源發(fā)送postMessage
otherWindow.postMessage(message, targetOrigin, [transfer]);
****解釋********
otherWindow:其他窗口的一個引用,比如 iframe 的 contentWindow 屬性、執(zhí)行 window.open 返回的窗口對象、或者是命名過或數(shù)值索引的 window.frames
message:將要發(fā)送到其他 window的數(shù)據(jù)。
targetOrigin:指定哪些窗口能接收到消息事件,其值可以是 *(表示無限制)或者一個 URI。
transfer:可選,是一串和 message 同時傳遞的 Transferable 對象。這些對象的所有權將被轉移給消息的接收方,而發(fā)送一方將不再保有所有權。
*****************
// 其他源的頁面,添加addEventlistener監(jiān)聽message
window.addEventListener('message', function (e) { // 監(jiān)聽 message 事件
messageEle.innerHTML = "從"+ e.origin +"收到消息: " + e.data;
});到此這篇關于JS中BroadcastChannel實現(xiàn)瀏覽器標簽頁通信的文章就介紹到這了,更多相關JS BroadcastChannel瀏覽器標簽頁通信內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

