当前位置: 首页 > news >正文

浏览器标签页通信实现打开新窗口播放音乐

浏览器标签页通信实现打开新窗口播放音乐

  • 1.项目场景
  • 2.模拟实现
    • 2.1通过窗口传递数据
    • 2.2使用broadcastChannel实现标签页间通信

1.项目场景

我们来看一个项目场景,下面是一个音乐网站。右侧是音乐列表。
在这里插入图片描述
点击列表第一首歌的播放按钮,浏览器会新建一个标签页,同时在新标签页展示这首歌的详情。
在这里插入图片描述
点击列表第二首歌的播放按钮,原来的标签页会重新展示第二首歌的详情(浏览器不会再新建一个标签页)。并且这个页面是没有进行刷新的。
在这里插入图片描述

2.模拟实现

在这里插入图片描述
如图,列表有三条数据,我们希望点击播放后会有上述某音乐网站这样子类似的效果。该问题的关键点是在新标签页需要知道主页面中点击的歌曲是哪一首。我们想到的是通过窗口传递数据:

2.1通过窗口传递数据

如下是文件夹结构:
在这里插入图片描述
index.html:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>音乐列表</title>
    <link rel="stylesheet" href="./css/index.css" />
  </head>
  <body>
    <div class="music-box">
      <div class="music-list">
        <div class="music-item">
          <span>晴天</span>
          <img data-name="晴天" src="./images/play.png" />
        </div>
        <div class="music-item">
          <span>黄昏</span>
          <img data-name="黄昏" src="./images/play.png" />
        </div>
        <div class="music-item">
          <span>童话</span>
          <img data-name="童话" src="./images/play.png" />
        </div>
      </div>
    </div>
  </body>
  <script>
    const btns = document.querySelectorAll(".music-item img");
    for (const btn of btns) {
      btn.onclick = function () {
        const name = this.dataset.name;
        //第二个参数传自定义的名字music,表示打开的窗口目标名字。
        // 如果找不到这个标签页名字就会新建一个标签页,取名为music
        //如果标签页存在,就会让该页面刷新页面
        window.open("./music.html?name=" + name, "music");
      };
    }
  </script>
</html>

musci.html:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>音乐详情</title>
    <link rel="stylesheet" href="./css/music.css" />
  </head>
  <body>
    <div class="music-detail">
      <span></span>
    </div>
    <script>
      function play(name) {
        const text = document.querySelector(".music-detail span");
        text.textContent = name + "正在播放";
      }
      const params = new URLSearchParams(location.search);
      const name = params.get("name");
      if (name) {
        play(name);
      }
    </script>
  </body>
</html>

如上,看样子需求是实现了,但每次点击播放时候,新标签页就是一次刷新,这明显与现代浏览器格格不入,如果音乐详情页面数据布局很多,会出现卡顿情况。如果能想办法让标签页不重新刷新就好了。那就要使用标签页的通信了。

2.2使用broadcastChannel实现标签页间通信

index.html:

 <script>
    const btns = document.querySelectorAll(".music-item img");
    //不管有多少标签页,只要能满足以下两个条件,他们就可以共用一个频道
    //a.标签页之间是同源的 b.频道名字要相同
    const channel = new BroadcastChannel("music");
    for (const btn of btns) {
      btn.onclick = function () {
        const name = this.dataset.name;
        //打开页签的数目
        let n = localStorage.getItem("tabs");
        if (!isNaN(n) && n > 0) {
          channel.postMessage(name);
        } else {
          window.open("./music.html?name=" + name, "_blank");
        }
      };
    }
  </script>

music.html:

<script>
      function play(name) {
        const text = document.querySelector(".music-detail span");
        text.textContent = name + "正在播放";
      }
      const params = new URLSearchParams(location.search);
      const name = params.get("name");
      if (name) {
        play(name);
      }
      const channel = new BroadcastChannel("music");
      let n = localStorage.getItem("tabs");
      if (isNaN(n)) {
        n = 0;
      }
      n++;
      localStorage.setItem("tabs", n);
      window.addEventListener("unload", () => {
        let n = localStorage.getItem("tabs");
        if (isNaN(n)) {
          n = 1;
        }
        n--;
        localStorage.setItem("tabs", n);
      });
      channel.addEventListener("message", (e) => {
        play(e.data);
      });
 </script>

后续我将写一篇文章https://blog.csdn.net/fageaaa/article/details/145659087讲述浏览器标签页的通信方式。

相关文章:

  • BDF(MD)
  • DeepSeek学术秘籍:如何让DeepSeek辅助论证?
  • 2月第九讲“探秘Transformer系列”
  • 无人机航迹规划: 梦境优化算法(Dream Optimization Algorithm,DOA)求解无人机路径规划MATLAB
  • Android设备 网络安全检测
  • CAS单点登录(第7版)27.开发人员
  • wx061基于ssm+vue+uniapp的疫情期间学生请假与销假系统小程序
  • Vue CLI 配置与插件
  • 1.【BUUCTF】[SUCTF 2019]EasyWeb
  • 【Docker】Docker Run 中指定 `bash` 和 `sh` 参数的区别:深入解析与实践指南
  • openGauss 3.0 数据库在线实训课程16:学习逻辑结构:表管理4
  • 小白零基础如何用cursor
  • 车载诊断框架 --- ECU运行周期operation cycle
  • MFC 自定义十六进制显示控件
  • 重生之我要当云原生大师(二十)访问网络附加存储:
  • Java:204 基于springboot零食销售商城的设计与实现
  • DOS网络安全
  • 2025年软件测试行业趋势分析
  • Vue2官网教程查漏补缺学习笔记 - Part2深入了解组件 - 4插槽5动态组件异步组件6处理边界情况
  • IntelliJ IDEA集成本地化部署的DeepSeek
  • 山东滕州车祸致6人遇难,醉驾肇事司机已被刑事拘留
  • 马克思主义理论研究教学名师系列访谈|石书臣:思政课是落实立德树人的关键
  • 江南华南较强降雨扰返程,北方大部需防风沙
  • 中国企业转口贸易破局之道:出口国多元化,内外贸一体化
  • 5月1日全国铁路发送旅客2311.9万人次,创历史新高
  • 北部艳阳高照、南部下冰雹,五一长假首日上海天气很“热闹”