用原生html+javascript实现上一首/下一首需维护currentindex索引,点击时更新索引、赋值audio.src、调用load()重载元数据、再play();须加ischanging锁防连点报错,并在ios safari中通过首次用户手势触发空音频建立播放上下文。

如何用原生 HTML + JavaScript 实现上一首/下一首按钮
纯 HTML 的 <button></button> 本身不能自动切换音频,必须配合 JavaScript 控制 <audio></audio> 元素的 src 和播放状态。核心是维护一个播放列表索引(如 currentIndex),点击按钮时更新索引、替换 src、再调用 play()。
常见错误是点击后音频没反应——大概率因为没处理 play() 被浏览器静音策略拦截(需用户手势触发),或新 src 加载未完成就调 play()。
- 把所有音频路径存进数组,比如
const playlist = ["song1.mp3", "song2.mp3", "song3.mp3"]; - 用一个变量(如
let currentIndex = 0;)记录当前播放项 - “下一首”按钮:先
currentIndex = (currentIndex + 1) % playlist.length,再audio.src = playlist[currentIndex],然后audio.load()(确保元数据重载),最后audio.play().catch(e => console.warn("Autoplay prevented:", e)) - “上一首”同理,但注意:如果当前是第一首,是否循环到末尾?用
(currentIndex - 1 + playlist.length) % playlist.length可安全处理负数取模
为什么 audio.load() 不能省略
直接改 src 后立刻 play(),在 Chrome/Firefox 中常失败,报错 DOMException: The element has no supported sources 或静音无声。这是因为浏览器没来得及解析新地址的音频格式和时长等元数据。
load() 强制重新加载并解析元数据,是触发后续 play() 成功的关键中间步骤。尤其当上下首格式不同(如 MP3 切到 WAV)时更必要。
- 不加
load():audio.src = "next.mp3"; audio.play();→ 大概率失败 - 正确顺序:
audio.src = "next.mp3"; audio.load(); audio.play(); - 可监听
loadeddata事件,在加载完成后才播放,更稳妥
如何避免重复点击导致播放中断或报错
用户快速连点“下一首”,可能触发多次 play(),而正在加载中的 <audio></audio> 对象对重复 play() 会抛 InvalidStateError,或打断当前加载流程。
解决思路是加状态锁:在开始加载新曲目前设 isChanging = true,加载完成或出错后再置为 false,按钮点击时先检查该标志。
- 声明
let isChanging = false;作为全局锁 - 按钮点击回调开头加
if (isChanging) return; - 设置新
src后立即isChanging = true; - 在
audio.onloadeddata或audio.onerror里设isChanging = false; - 也可用
audio.readyState判断是否已就绪,但不如显式锁直观可靠
移动端 Safari 的特殊限制
iOS Safari 对自动播放管控极严:即使有用户点击,若音频未设置 muted="true",且未实际播放过任何音频,首次调 play() 仍可能被拒绝。这不是 bug,是策略。
绕过方法只有两个:要么首首默认静音(不现实),要么在页面初始化时用一次用户点击(如“开始播放”按钮)触发一次无声音频的 play(),建立播放上下文。
- 加一段不可见的空音频:
<audio id="init-audio" src="data:audio/wav;base64,UklGRigAAABXQVZFZm10IBAAAAABAAEARKwAAIwsAAACAAADY2xpcGluZwAAAAABAAAAABAAAAA="></audio> - 首次点击任意控制按钮时,先对它调一次
initAudio.play(),之后所有真实音频就能正常播放 - 这个 trick 必须发生在用户手势内(比如按钮
onclick里),不能在DOMContentLoaded自动执行
没处理这点,你的“下一首”在 iPhone 上大概率点十次只响一次——不是代码问题,是平台规则卡死的。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











