利用BroadcastChannel实现单页面播放

利用BroadcastChannel实现单页面播放

标签&分类
Javascript
发表时间
Mar 1, 2023 07:42 AM
描述
利用BroadcastChannel来实现多次点击,只打开单个播放页面
更新时间
Last updated March 6, 2023
场景如下:
歌曲列表页面点击Item,打开播放页面,播放对应歌曲。如果播放页面存在,则直接播放新歌曲
 
解决思路,
利用BroadcastChannel 实现页面间通信,列表页面点击歌曲发送信息,播放页面收到信息,播放新歌曲
要实现打开单播放页面,就要想办法做出如下判断
  1. 列表页面点击的时候,如果没有播放页面,则打开,如果有,则发送消息
  1. 利用BroadcastChannel 来做判断(设置页面ID,并把id加入集合,如果集合为空则需要打开新页面,不为空则发送信息)
 
歌曲列表页面:
// 列表页面 // 引入Channel.js const playBtns = document.querySelectorAll('.play'); const channel = createChannel('music'); for (const btn of playBtns) { btn.onclick = (e) => { if(channel.listeners.size === 0) { //还没有播放页面被打开 window.open(`/play.html?name=${e.target.dataset.name}`, '_blank') } else { channel.postMessage({ musicName: e.target.dataset.name }) } } }
播放页面
// 播放页面 // 引入Channel.js function play(name) { console.log(`当前播放的是:${name}`) } const channelPlay = createChannel('music'); channelPlay.addEventListener('message', (e) => { // 收到广播,播放新歌曲 if(e.data.musicName) { play(e.data.musicName) } }) function init() { // 首次打开, 获取url参数去播放 const url = new URL(location.href); const name = url.searchParams.get('name'); if(!name) return; play(name) } init()
Channel.js
function createId(name) { const key = `channel-${name}`; let id = +localStorage.getItem(key) || 0; id++; localStorage.setItem(key, id.toString()); return id; } function sendMessage(channel, msg) { channel.postMessage({ id: channel.id, msg, }) } function createChannel(name) { const channel = new BroadcastChannel(name); channel.id = createId(name); channel.listeners = new Set(); // 0 表示离开, 1表示进入,给出反馈 2 表示收到信息,无需反馈 sendMessage('1', channel); window.addEventListener('unload', () => { // 当页面离开的时候,需要删除当前页面的channel id sendMessage(channel, '0'); }) channel.addEventListener('message', (e) => { if(e.data.msg === '1') { // 页面创建 新加id sendMessage(channel, '1-1'); channel.listeners.add(e.data.id); } else if(e.data.msg === '2') { channel.listeners.add(e.data.id); } else if(e.data.msg === '0') { // 收到页面离开信号,删除id channel.listeners.delete(e.data.id); } }) return channel; }