用单个<audio>动态切换src实现高效音乐列表:绑定data属性存歌曲信息,preload="none",点击时load()再play(),注意用户手势触发、跨域、文件编码及移动端兼容性。
<audio> 实现可点击播放的歌曲列表直接用原生 <audio> 标签配合 <ul><li> 就能做出基础音乐列表,不需要框架或额外库。关键在于把每首歌的 src 和元信息(如标题、时长)绑定到可交互元素上,再通过 JavaScript 控制播放/暂停。
常见错误是把多个 <audio> 全部写死在 HTML 里,导致页面加载慢、内存占用高、切换卡顿。更合理的方式是:只保留一个 <audio> 实例,点击列表项时动态改它的 src 并调用 load() 和 play()。
<li> 加 data-src、data-title 等自定义属性存歌曲信息<audio> 标签加 preload="none",避免页面加载时预抓取所有音频audio.load(),再 audio.play(),否则部分浏览器(如 Safari iOS)可能静音失败currentTime,避免连续点击同一首时从中间开始播这是最常遇到的问题,通常不是代码逻辑错,而是被浏览器策略或细节卡住。
audio.play() 必须由用户手势触发(比如 click、touchstart),不能在 setTimeout 或 fetch 回调里直接调;否则 Chrome 会报 DOMException: play() failed because the user didn't interact with the document
file:// 协议打开 HTML,Chrome 会因安全策略拒绝加载,得用 python3 -m http.server 启个本地服务controlsList="nodownload noplaybackrate" 避免部分安卓浏览器隐藏控件,同时确保 autoplay 不写死——它在多数移动浏览器中被禁用高亮靠 CSS 类切换,进度同步靠监听 timeupdate 事件,但要注意性能和精度。
立即学习“前端免费学习笔记(深入)”;
<li> 添加 class="playing",用 CSS 设置背景色或图标;切换前先移除旧的 playing 类timeupdate 里频繁更新 DOM 文本(比如实时刷新“02:15 / 03:42”),建议节流到 250ms 一次,或只在 seeking 和 ended 时更新关键状态audio.duration 判断是否加载完成;未就绪时值为 NaN,直接读会出错,应先监听 loadedmetadata 事件再取值<input type="range"> 最稳妥,比自绘 <div> 更易控制拖动和兼容性;拖动时设 audio.currentTime,同时防止拖到超出范围Howler.js 或 WaveSurfer.js
纯列表播放,原生足够;只有当你需要波形图、多音轨混音、精确时间轴定位、或 Web Audio API 特性时,才值得引入。
Howler.js 对 Safari 的 web audio 兼容更好,适合要做淡入淡出、音量分组、或后台持续播放的场景;但它会让包体积增加 ~15KB(gzip 后)WaveSurfer.js 专攻可视化,如果你要显示波形、支持区域选择、或导出某一段,它比手写 canvas 绘制靠谱得多;但默认不处理播放逻辑,仍需自己绑定列表点击fetch 加载音频,若你的歌曲在非 CORS 环境(比如某些内网 NAS)下,原生 <audio src="..."> 反而更稳真正容易被忽略的是音频格式兼容性:Safari 不支持 OGG,Firefox 对某些 AAC 编码有 bug,所以至少准备 MP3 + (可选) WAV 双格式 fallback,用 <source> 嵌套声明。