APlayer 销毁与重建最佳实践
什么时候需要销毁
以下场景需要主动销毁 APlayer 实例:
- 单页应用(SPA)路由切换:组件卸载时必须销毁
- 列表动态增删:播放器容器从 DOM 中移除时
- 完整重新初始化:参数变化后想从零开始
- 页面彻底关闭:beforeunload 时(可选)
基本销毁
ap.destroy();
ap = null; // 清空引用
销毁后:
- 停止播放
- 清除所有事件绑定
- 清空 DOM 容器内容
- 释放音频资源(浏览器的音频解码会停止)
- 触发
destroy事件
Vue / React 组件中
Vue 3 Composition API
<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue';
import 'APlayer/dist/APlayer.min.css';
import APlayer from 'APlayer';
const playerRef = ref(null);
let ap = null;
onMounted(() => {
ap = new APlayer({
container: playerRef.value,
audio: [...]
});
});
onBeforeUnmount(() => {
if (ap) {
ap.destroy();
ap = null;
}
});
</script>
React useEffect
import { useEffect, useRef } from 'react';
import 'APlayer/dist/APlayer.min.css';
import APlayer from 'APlayer';
export function Player() {
const playerRef = useRef(null);
const apRef = useRef(null);
useEffect(() => {
apRef.current = new APlayer({
container: playerRef.current,
audio: [...]
});
// 清理函数 = 组件卸载时执行
return () => {
if (apRef.current) {
apRef.current.destroy();
}
};
}, []);
return <div ref={playerRef} />;
}
销毁后重建
销毁后可以直接在同一个容器里重新实例化:
// 第一次
const ap1 = new APlayer({ container: el, audio: [...] });
ap1.destroy();
// 第二次(用新的参数)
const ap2 = new APlayer({
container: el, // 同一个 DOM 元素
theme: '#333', // 不同主题色
audio: [...] // 不同的歌曲列表
});
不需要手动清空容器内容——destroy() 已经做了。直接 new 就行。
为什么必须销毁
内存泄漏
如果你不销毁就直接把容器从 DOM 中移除:
- 音频元素的 event listener 仍然挂着
- HLS 实例(如果有)仍然在后台运行
- 播放仍然继续(你看不见但还在消耗 CPU 和流量)
这就是内存泄漏。
播放器状态不一致
销毁后不重建,而只是"修改一下参数":
const ap = new APlayer({ ... });
// 错误的尝试:直接修改属性
ap.options.theme = '#333'; // 改了不会自动生效
ap.options.audio = [...]; // 也不会重新渲染
APlayer 在初始化时就根据参数创建好了 DOM 和内部状态。修改 ap.options 不会触发重新渲染。正确做法是销毁后重新创建。
多次 create 不 destroy
// 错误:每次路由切换都创建新实例,但旧的没销毁
router.onChange(function() {
const ap = new APlayer({ ... }); // 旧的 ap 被覆盖了,但没销毁!
});
每次 new APlayer() 都会:
- 创建新的 audio 元素
- 绑定新的事件监听
- 如果是 HLS,还会创建新的 Hls 实例
旧的仍然在运行——尤其是 player.play() 不会因为变量被覆盖就停止。你会得到多个看不见的播放器同时播放。
销毁 vs 暂停
| 对比项 | pause() | destroy() |
|---|---|---|
| 停止播放 | ✅ | ✅ |
| 释放事件监听 | ❌ | ✅ |
| 释放 DOM | ❌ | ✅ |
| 后续可恢复 | ✅ | ❌ |
| 内存 | 占用 | 释放 |
暂停是临时停止播放,播放器还在;销毁是彻底清理。
自定义资源清理
如果你用了 customAudioType 创建了额外资源(如 Hls 实例、Blob URL),需要在 destroy 事件里手动清理:
let hlsInstance = null;
const ap = new APlayer({
audio: [{ type: 'customHls', ... }],
customAudioType: {
customHls: function(audioElement, audio, player) {
hlsInstance = new Hls();
hlsInstance.loadSource(audio.url);
hlsInstance.attachMedia(audioElement);
}
}
});
// 监听销毁事件,清理自己创建的资源
ap.on('destroy', function() {
if (hlsInstance) {
hlsInstance.destroy();
hlsInstance = null;
}
});