同源跨窗口通信:网易云音乐不同标签页打开同一页面,暂停原先标签页音频播放

这篇具有很好参考价值的文章主要介绍了同源跨窗口通信:网易云音乐不同标签页打开同一页面,暂停原先标签页音频播放。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

原文见:语雀

有个声音很好听的小帅哥问我说,如果当前浏览器打开一个标签页,页面播放着音乐,然后相同的链接又在另外一个页面打开,该如何将之前的页面音频停止播放。
有小帅哥问问题,我当然要回答啦(其实是我不得不答)🤣
我一想,这是跨窗口通信,用postMessage,不过我忘了这个api具体怎么使用了。小帅哥提醒说,postMessage通信时,无法获取到原先标签页的window,所以无法改变原先的window内容。
最后,我想到的解决方案是localStorage存储播放状态,并将状态发送给后端,然后websockert保持前后端通信,在打开新标签页的时候,原先标签页监听到websocket的消息,暂停音乐播放。
虽然知道这样占用带宽,不是好的解决方案,但是一时也想不到什么好的方案。

我觉得这属于同源跨窗口通信类型的技术问题。
有空就在网上搜搜搜了起来,并结合自己以前的知识整理,发现有以下方案可以实现
● websocket
● 监听localStorage的storage事件(推荐)
● Broadcast channel (兼容性不佳)

websocket

不仅能跨窗口,还能跨浏览器,兼容性最佳,到那时需要消耗浏览器资源。

localStorage的storage事件
storage事件会在数据更新时触发,并且会在所有可访问到存储对象的window对象上触发,导致当前数据改变的window对象除外。

// a标签页,原先标签页
window.onstorage = event => { // 同window.addEventListener('storage', () => {})
  if (event.key != 'changeVedioStatus') return;
  console.log('音频在另一页面打开了')
}

// b标签,新打开的标签页
localStorage.setItem('changeVedioStatus', Date.now());

回想了一些,我想到了localStorage状态,但是却因为不记得storage事件,所以没有想到了好的解决方案。其实在小帅哥的提醒下,我应该从localStorage的角度出发考虑问题,可以试着想“是否有事件能实时监听到storage的改变”

Broadcast channel API

这个api的功能更全,但是浏览器支持情况不好,有些库基于localStorage来polyfill该API

// a标签页
const bc = new BroadcastChannel('changeVedioStatus'); // 连接到广播频道
bc.postMessage(Date.now()); // 一定要postMessage过去,不然不会监听到onmessage,就不能触发onmessage里的事件

bc.onmessage = (ev) => {
  if (ev.currentTarget != 'changeVedioStatus') return;
  alert(event.data); // 我打开啦
  console.log(ev)
}

写到这里,我突然发现,浏览器刷新时会触发bc.onmessage事件,如果是切换标签页,并不会切换,实际上,我觉得如果切换标签页,也应该让当前页面播放,原先页面暂停播放。就想到了切换标签页的document.addEventListener(‘visibilitychange’, () => {})
代码主要逻辑如下,大致实现了标签切换,播放状态自动切换

  const broadcast = () => {
    const bc = new BroadcastChannel('changeVedioStatus'); // 连接到广播频道
    const audio = audioRef.current;

    document.addEventListener('visibilitychange', () => {
      // a标签页发送消息
      bc.postMessage(Date.now());
      
      // b标签页接收到消息,关闭音频
      bc.onmessage = (ev) => {
        if (document.visibilityState !== 'hidden') return;
        // b标签页
        if (ev?.currentTarget?.name !== 'changeVedioStatus') return;
        audio?.pause();
        console.log(`%c 我关闭了:::`, 'background-color: red;font-size:14px;');
      };

      // a标签页播放
      if (document.visibilityState === 'visible') {
        audio?.play();
        console.log(`%c 我打开了:::`, 'background-color: pink;font-size:14px;');
      }
    });

    return () => {
      bc.close();
    };
  };

  useEffect(() => {
    broadcast();
  }, []);


// 音频
<audio controls ref={audioRef}>
  <source src="horse.ogg" type="audio/ogg" />
  <source src="http://img0.xinmin.cn/2021/11/25/20211125150754275040.mp3" type="audio/mpeg" />
  您的浏览器不支持 audio 元素。
</audio>

postMessage(不可行)

因为曾想到postMessage,所以我自己又尝试了一下是否可以实现,发现这个api,同源的origin是一样的,所以无法区别两个窗口,也就是a标签页用了window.postMessage,想发消息给b标签页,但是因为origin是相同的,根本判断不出来是是想要发给b的,只要在b中执行就行了。因为代码是同一个页面,所以a发出的消息,a自己也会执行,

// a想发消息给b
window.postMessage('changeVedioStatus', '*');
window.addEventListener('message', (event) => {
  // 无法判断event里的消息,a是否需要执行,所以a、b标签都会执行这个方法
  if (document.visibilityState !== 'hidden') return;
  if (event.data !== 'changeVedioStatus') return;
  audio?.pause(); // 本想让b停止播放,结果a自己也停止播放了
});

想到当时小帅哥说,网易云音乐其实在localStorage出现之前,就已经实现了这项技术,所以我觉得,应该还是会有其他方案的。
经过我坚持不懈的努力,发现…
=> 20220325-aSuncat:发现暂时还木有搜到其他的~~~🤣文章来源地址https://www.toymoban.com/news/detail-400661.html

到了这里,关于同源跨窗口通信:网易云音乐不同标签页打开同一页面,暂停原先标签页音频播放的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • QT如何实现不同窗口之间的通信

    方法: 用qt的信号与槽来实现   1,首先,对发送信号的窗口,自定义信号,和槽函数。   如:From1   signals:     void  SendData (QString s);  //信号   private slots: void  SendSlot (); //传递信号的函数,这个函数的主要功能就是,发送 SendData 这个信号     //槽函数实现 void Form1:: S

    2024年02月09日
    浏览(37)
  • 同一台宿主机不同的docker-compose下的容器互相通信;查看docker的network使用情况

    我的 docker 版本: 24.0.2 docker-compose 版本: 1.29.2 linux 是 ubuntu 20.04 在使用 docker 部署环境的时候大多用 docker-compose 来编排,参数的配置会清晰一点。 通常一个容器一个 docker-compose.yml 文件。 这就使得不同 docker-compose 下的容器不能自动的互相通信。 那么顺着这个思路往下想,

    2024年02月08日
    浏览(45)
  • iframe/window.open/a三种标签打开新页面或新窗口设置请求头;实现免密登录

    对于前端来说,一般在登录获取token之后会把token存入缓存以及放置在Request Headers请求头中,但是使用iframe/window.open/a这三种标签打开新页面或新窗口是没有办法把请求头带过去的,这个时候就需要自己设置请求头,有如下有两种办法: 方法一(不推荐): 第一种方法可以说是最

    2024年02月12日
    浏览(60)
  • 网易云音乐开发--音乐播放暂停切换上下首功能实现

     问题就是我们点击播放,暂停之后,再次播放,它会多次发起请求。而我们现在对它的优化是,不需要重复的发起请求 这里我们通过把musicLink改为形参的方式,如果有给它传入参数,没有链接那么就让它发起请求,如果有那就继续走下去。而且我们将musicLink保存到data中 

    2024年02月06日
    浏览(41)
  • 微信小程序之网易云音乐的实现-云音乐

    基本介绍 基本功能都实现了,音乐的上一首下一首播放等,顺便把进度条的拖动播放写了下 主页的 每日推荐界面 写了 ,登录通过账号密码登录 (你也可以自己加一个验证码或者邮箱登录 ) 基于iPhone6(375*667分辨率)开发,后面一些计算都是通过获取当前屏幕下的尺寸来计算的,但是不

    2024年02月10日
    浏览(41)
  • Python爬虫网易云音乐,Tkinter制作音乐播放器

    目录 一、效果展示 二、环境 三、实现过程 四、源码 页面的美化以及功能还有待升级~ 先来说一下已有功能吧: 可以在搜索框中通过歌曲或歌手名称进行搜索,效果和在网易云官网搜索一样。 点击开始下载,就会将搜索结果的第一条歌曲下载到指定文件夹 下载完毕后,会遍

    2024年02月04日
    浏览(51)
  • 安装UWP版网易云音乐

    下载APPX文件JasonWei512/NetEase-Cloud-Music-UWP-Repack: 网易云音乐 UWP 不更新版 (github.com) 下载安装 LTSC-Add-MicrosoftStore/Microsoft.NET.Native.Runtime.1.6_1.6.24903.0_x64__8wekyb3d8bbwe.Appx at master · kkkgo/LTSC-Add-MicrosoftStore (github.com)

    2024年02月11日
    浏览(35)
  • docker安装网易云音乐(yesplaymusic)

    演示地址:https://music.qier222.com/ 镜像地址:https://hub.docker.com/r/fogforest/yesplaymusic/tags 项目地址:https://github.com/qier222/YesPlayMusic ✨ 特性 ✅ 使用 Vue.js 全家桶开发 🔴 网易云账号登录(扫码/手机/邮箱登录) 📺 支持 MV 播放 📃 支持歌词显示 📻 支持私人 FM / 每日推荐歌曲 🚫🤝

    2024年02月05日
    浏览(53)
  • Python爬虫 - 网易云音乐下载

    爬取网易云音乐实战,仅供学习,不可商用,出现问题,概不负责! 分为爬取网易云歌单和排行榜单两部分。 因为网页中,只能显示出歌单的前20首歌曲,所以仅支持下载前20首歌曲(非VIP音乐) 具体过程: 1.通过抓包,获取到请求头 2.发送请求,获取到网页源代码,通过

    2024年01月19日
    浏览(46)
  • 网易云音乐开发--完善video模块

    老样子,npm start开启服务器 说一下问题  现在打开多个视频会让他,同时播放,相当的吵闹。我们只需要一次只有一个视频播放 看文档,我们的思路是点击这个视频,关闭上次视频   我们传入这个id 现在只能实现找到上一个视频的实例对象 这就能实现确定点击播放的视频和

    2024年02月04日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包