用文字记录生活,留下美好瞬间
原创

标签页间通信 - 播放音乐

共 6,086 字,需阅读 15 分钟
2019/08/17 上午
350 次阅读

#原始通信技术

要在 index.html 页面中实现点击 li 列表项时打开新的 music.html 页面并播放对应的本地歌曲:

假设你的HTML结构如下:

          
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
<!-- index.html --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>音乐播放器</title> </head> <body> <ul class="song-list"> <li data-song="song1.mp3">歌曲1</li> <li data-song="song2.mp3">歌曲2</li> <li data-song="song3.mp3">歌曲3</li> </ul> <script> const liList = document.querySelectorAll('li'); liList.forEach(item => { item.addEventListener('click', () => { const name = item.dataset.name console.log(item.dataset.name); window.open('music.html?name=' + name, '_blank') }) }) </script> </body> </html>

有个li列表,每个li列表项都有data-name属性,点击列表项,会触发点击事件,打开一个新窗口,并传递data-name属性的值。

          
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
<!-- music.html --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title></title> </head> <body> <audio controls></audio> <script> const audio = document.querySelector('audio') const play = (name) => { audio.src = `audio/${name}` document.title = name audio.play() } const search = new URLSearchParams(location.search) const name = search.get('name') play(name) </script> </body> </html>
原始通信技术
原始通信技术

music.html 中,当它被打开时,就会触发,通过url参数获取实际要播放的文件名,从而播放音乐

然而,请注意,由于浏览器安全策略限制,直接播放本地文件通常不可行,除非你正在运行一个本地服务器环境,并且音频文件位于可被服务器访问的路径下。

但是这样有个问题,每次点击,都会打开一个新的页面,我需要实现如果不存在他就打开,如果存在了就切换过去。不用再打开一个新的窗口了,这个时候我们就需要换个思路,使用窗口间通信。

#BroadcastChannel

它允许来自同源的不同窗口、标签页或上下文环境之间的简单通信,为构建更为复杂和交互性更强的Web应用程序提供了可能

在现代Web开发中,浏览器提供的API工具箱日益丰富,其中BroadcastChannel就是一项颇具实用价值的API。它允许来自同源的不同窗口、标签页或上下文环境之间的简单通信,为构建更为复杂和交互性更强的Web应用程序提供了可能。

BroadcastChannel是HTML5引入的一种全新的通信机制,通过创建一个命名的通道,使得同一个源下的不同上下文(如页面、iframe或Service Worker)可以进行双向通信。每个通道都是独立的,并且消息传递具有发布/订阅模式的特点,即在一个通道上发布消息的所有上下文都可以接收到该消息。

#使用BroadcastChannel

要开始使用BroadcastChannel,首先需要创建一个新的实例:

          
  • 1
let channel = new BroadcastChannel('my-channel');

这里的 'my-channel' 就是你创建的频道名称,任何拥有相同频道名称的BroadcastChannel实例都可以互相发送和接收消息。

#发送消息

发送消息至指定频道非常简单,只需调用postMessage()方法:

          
  • 1
channel.postMessage({type: 'message', data: 'Hello from one tab to another!'});

这里的消息可以是任何能够被序列化为JSON的数据类型。

#接收消息

为了监听并处理从频道接收到的消息,可以添加事件监听器到BroadcastChannel实例上:

          
  • 1
  • 2
  • 3
channel.addEventListener('message', function(event) { console.log('Received:', event.data); });

上述代码会在接收到新消息时打印出消息内容。

接下来,改造我们写的音乐播放器

          
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
<!-- index.html --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> ul { width: 140px; } li { list-style: none; background-color: #0088f5; margin-bottom: 20px; padding: 5px 10px; border-radius: 4px; color: #fff; cursor: pointer; } </style> </head> <body> <ul> <li class="item" data-name="这就是爱.mp3">这就是爱</li> <li class="item" data-name="躲避的爱.mp3">躲避的爱</li> <li class="item" data-name="百花香.mp3">百花香</li> </ul> <script> let isExist = false // 创建通信频道 const channel = new BroadcastChannel('music'); channel.addEventListener('message', (event) => { // 当开启一个音乐时,记录窗口的开启状态 if (event.data.type === 'online') { isExist = true } }) const liList = document.querySelectorAll('li'); liList.forEach(item => { item.addEventListener('click', () => { const name = item.dataset.name if (!isExist) { // 如果不存在播放窗口,打开一个 window.open('music.html?name=' + name, '_blank') } else { // 如果存在播放窗口,发送消息 channel.postMessage({ type: 'play', name }) } }) }) </script> </body> </html>

通过创建一个BroadcastChannel实例(名为'music')来实现在不同浏览器上下文间的通信。当接收到'music'通道的消息且类型为'online'时,会将全局变量isExist设为true,表示音乐播放窗口已经打开,通过BroadcastChannel向该窗口发送一个消息,消息内容包括要播放的歌曲名称,以便于在已打开的音乐播放窗口中开始播放对应的歌曲。如果发现当前没有已存在的音乐播放窗口(即isExist为false),则会在新标签页中打开music.html并将选定歌曲的名称作为查询参数

          
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
<!-- music.html --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <audio controls></audio> <script> const channel = new BroadcastChannel('music'); channel.addEventListener('message', (event) => { if (event.data.type === 'play') { play(event.data.name) } }) channel.postMessage({ type: 'online' }) const audio = document.querySelector('audio') const play = (name) => { audio.src = `audio/${name}` document.title = name audio.play() } const search = new URLSearchParams(location.search) const name = search.get('name') play(name) </script> </body> </html>

利用JavaScript实现了跨标签页通信,根据接收到的消息播放指定音频文件,并能从URL参数中获取初始播放的音频文件名。页面上有一个可控制的音频播放器组件。

BroadcastChannel
BroadcastChannel

#四、注意事项

尽管BroadcastChannel功能强大,但也需要注意以下几点:

  1. 同源策略限制:只有同源的上下文才能共享同一个BroadcastChannel。
  2. 数据安全:由于所有订阅同一频道的上下文都能接收到消息,因此不要发送敏感信息,应确保数据传输的安全性。
  3. 资源管理:关闭不再使用的BroadcastChannel实例以释放资源。

总结来说,BroadcastChannel API提供了一种简洁且强大的方式来实现同源上下文间的通信,为提升Web应用的功能性和用户体验提供了更多可能性。在实际项目中,根据需求合理运用此API,无疑将使我们的Web应用更加智能与灵活。

自由转载 - 署名 - 非商业性使用
https://zhangwurui.cn/article/58
0/0条看法
访客身份
在下有一拙见,不知...
期待你的捷足先登