网页跨标签页控制,以简单播放器为例
-
实现原理
使用
BroadcastChannel
API可以在同源的条件下创建自定义命名的频道,频道名相同可以相互通信。使用message
事件监听,使用postMessage
发送信息 -
项目代码
-
代码树
core.js index.html play.html
-
core.js
const musicList=[ {name:'嘉宾',url:'https://cdn-static.xxcheng.cn/static/blog/images/2022/06/15/f54fb5f042ae6fe0bf1a8af731ae0db7.mp3'}, {name:'嗷呜一口仙贝 - 必杀技',url:'https://cdn-static.xxcheng.cn/static/blog/images/2023/05/08/dc97503c338d3ea64e266425bdf8b54e.mp3'}, {name:'毛不易 - 入海',url:'https://cdn-static.xxcheng.cn/static/blog/images/2023/05/08/fb41c9001784b0b25c4141f29a7bbf7b.mp3'} ] function createId(name){ let key=`channel-${name}-id`; let id=localStorage.getItem(key); if( !id ){ id=0; } id++; localStorage.setItem(key,id.toString()); return id; } function sendMsg(channel,msg,type='default'){ channel.postMessage({ id:channel.id, type, msg }); } function createChannel(name,type='default'){ const channel= new BroadcastChannel(name); channel.id=createId(name); channel.listeners=new Set(); sendMsg(channel,type,'hello'); window.addEventListener('unload',function(){ sendMsg(channel,type,'bye'); }); channel.addEventListener('message',function(e){ if( e.data.type==='bye' ){ console.log('bye',e.data.id); channel.listeners.delete(e.data.msg+'-'+e.data.id); }else if( e.data.type==='hello' ){ console.log('hello',e.data.id); channel.listeners.add(e.data.msg+'-'+e.data.id); sendMsg(channel,type,'rehello'); }else if( e.data.type==='rehello' ){ console.log('rehello',e.data.id); channel.listeners.add(e.data.msg+'-'+e.data.id); } }) return channel; }
-
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>首页</title> </head> <body> <script src="./core.js"></script> <h3>在线播放音乐</h3> <table border="1"> <thead> <tr> <td>名称</td> <td>播放</td> </tr> </thead> <tbody id="music-container"></tbody> </table> <script> const musicContainer=document.querySelector('#music-container'); let html=''; musicList.forEach((musicItem,index)=>{ html+=`<tr> <td>${musicItem.name}</td> <td><button onclick="toPlay('${index}')">播放</button></td> </tr>`; }) musicContainer.innerHTML=html; const channel=createChannel('music'); console.log(channel); function toPlay(index){ if( channel.listeners.size>0 ){ for( let name of channel.listeners ){ if( name.indexOf('player')===0 ){ console.log('有播放器了~~~'); sendMsg(channel,index,'switchSong'); return; } } } window.open('./play.html?id='+index); } </script> </body> </html>
-
play.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>播放页面</title> </head> <body> <script src="./core.js"></script> <audio id="musicEl" controls autoplay></audio> <script> const url=new URL(location.href); const musicId=url.searchParams.get('id'); const musicEl=document.querySelector('#musicEl'); if( musicList[musicId] ){ musicEl.src=musicList[musicId].url; musicEl.play(); } const channel=createChannel('music','player'); channel.addEventListener('message',e=>{ if( e.data.type==='switchSong' ){ musicEl.src=musicList[e.data.msg].url; } }); </script> </body> </html>
-
-
实现效果浏览
-
参考链接
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。