Vue 和 React 中集成 APlayer 组件
组件封装 vs 原生实例
APlayer 本身是一个原生 JavaScript 类。在 Vue / React 项目中,你可以:
- 原生引入(通过 ref + useEffect 手动管理实例生命周期)
- 使用社区封装组件(像普通组件一样使用 props 配置)
两种方式都可行。下面分别介绍。
Vue 中的原生引入
<template>
<div ref="playerRef"></div>
</template>
<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: [
{ name: '歌曲一', artist: '艺术家A', url: '1.mp3', cover: '1.jpg' },
{ name: '歌曲二', artist: '艺术家B', url: '2.mp3', cover: '2.jpg' }
]
});
});
onBeforeUnmount(() => {
if (ap) {
ap.destroy();
ap = null;
}
});
</script>
关键点:
onMounted时创建实例(DOM 已就绪)onBeforeUnmount时销毁实例(防止内存泄漏)- 用 ref 拿到容器元素
React 中的原生引入
import { useRef, useEffect } from 'react';
import 'APlayer/dist/APlayer.min.css';
import APlayer from 'APlayer';
export function MusicPlayer() {
const playerRef = useRef(null);
const apRef = useRef(null);
useEffect(() => {
apRef.current = new APlayer({
container: playerRef.current,
audio: [
{ name: '歌曲一', artist: '艺术家A', url: '1.mp3', cover: '1.jpg' },
{ name: '歌曲二', artist: '艺术家B', url: '2.mp3', cover: '2.jpg' }
]
});
return () => {
if (apRef.current) {
apRef.current.destroy();
}
};
}, []);
return <div ref={playerRef} />;
}
Vue-APlayer 组件
GitHub 地址:搜索 SevenOutman/vue-aplayer
这是一个更现代化的 Vue 组件封装,支持 Composition API 和 TypeScript。
<template>
<div class="wrapper">
<APlayer :audio="audio" theme="#333" />
</div>
</template>
<script setup>
import APlayer from '@moefe/vue-aplayer';
const audio = [
{ name: '歌曲一', artist: '艺术家A', url: '1.mp3', cover: '1.jpg' },
{ name: '歌曲二', artist: '艺术家B', url: '2.mp3', cover: '2.jpg' }
];
</script>
react-aplayer 组件
GitHub 地址:搜索 sabrinaluo/react-aplayer
import APlayer from 'react-aplayer';
const audio = [
{ name: '歌曲一', artist: '艺术家A', url: '1.mp3', cover: '1.jpg' },
{ name: '歌曲二', artist: '艺术家B', url: '2.mp3', cover: '2.jpg' }
];
export default function Player() {
return <APlayer audio={audio} theme="#333" />;
}
在组件中响应播放状态变化
APlayer 实例的事件系统可以映射到 Vue/React 的状态更新:
Vue 示例
<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue';
import 'APlayer/dist/APlayer.min.css';
import APlayer from 'APlayer';
const isPlaying = ref(false);
const currentIndex = ref(0);
const playerRef = ref(null);
let ap = null;
onMounted(() => {
ap = new APlayer({
container: playerRef.value,
audio: [...]
});
ap.on('play', () => { isPlaying.value = true; });
ap.on('pause', () => { isPlaying.value = false; });
ap.on('listswitch', (index) => { currentIndex.value = index; });
});
onBeforeUnmount(() => {
if (ap) ap.destroy();
});
</script>
React 示例
import { useState, useEffect, useRef } from 'react';
import 'APlayer/dist/APlayer.min.css';
import APlayer from 'APlayer';
export function Player() {
const [isPlaying, setIsPlaying] = useState(false);
const [currentIndex, setCurrentIndex] = useState(0);
const playerRef = useRef(null);
const apRef = useRef(null);
useEffect(() => {
apRef.current = new APlayer({
container: playerRef.current,
audio: [...]
});
apRef.current.on('play', () => setIsPlaying(true));
apRef.current.on('pause', () => setIsPlaying(false));
apRef.current.on('listswitch', (index) => setCurrentIndex(index));
return () => {
if (apRef.current) apRef.current.destroy();
};
}, []);
return (
<div>
<div ref={playerRef} />
<span>{isPlaying ? '正在播放' : '已暂停'}</span>
<span>当前歌曲索引: {currentIndex}</span>
</div>
);
}