Vue.js周期性播放音频问题:仅刷新时播放,需改为每15秒自动播放
解决Vue.js每15秒自动播放更新音频的问题
核心问题分析
你的代码主要有两个关键问题导致无法周期性自动播放:
- 父组件中错误地将
computed对象赋值给ref的value,破坏了响应式更新逻辑 - 子组件仅在初始化时播放音频,未监听
props更新来触发新的播放流程
父组件修复代码
<template> <div> <CommunicateVoice v-if="filenames[0]" :files="filenames[0]"/> </div> </template> <script setup> import { onMounted, ref, computed } from "vue"; import axios from "axios"; import CommunicateVoice from './CommunicateVoice.vue'; const lands = ref([]); // 直接声明computed属性,依赖lands自动更新 const filenames = computed(() => { return lands.value.map(item => { const digits = item.numbershow.toString().split(''); return digits.map(digit => `https://koh-abx.com/sound/${digit}.mp3`); }); }); onMounted(async () => { const fetchData = async () => { const res = await axios.get("https://koh-abx.com:50100/onboardlands"); lands.value = res.data; }; fetchData(); setInterval(fetchData, 15000); }); </script>
修复说明
- 把
filenames改为直接声明的computed属性,不再动态赋值给ref - 每次
fetchData更新lands后,filenames会自动计算新的音频地址列表,触发子组件的props更新
子组件修复代码
<template> <div> <audio ref="audioEl" /> </div> </template> <script> import { onMounted, ref, watch, onBeforeUnmount } from 'vue'; export default { props: { files: { type: Array, required: true, }, }, setup(props) { const audioEl = ref(null); const currentFileIndex = ref(0); // 封装播放初始化逻辑,复用性更强 const initPlay = () => { // 清理旧的音频实例 if (audioEl.value) { audioEl.value.removeEventListener("ended", playNextFile); audioEl.value.pause(); audioEl.value.currentTime = 0; audioEl.value.parentNode?.removeChild(audioEl.value); } // 创建新音频实例并开始播放 audioEl.value = new Audio(); audioEl.value.addEventListener("ended", playNextFile); document.body.appendChild(audioEl.value); currentFileIndex.value = 0; audioEl.value.src = props.files[currentFileIndex.value]; audioEl.value.play().catch(err => console.error("播放失败:", err)); }; onMounted(() => initPlay()); // 监听音频文件列表变化,自动重新播放 watch(() => props.files, initPlay, { deep: true }); // 组件卸载时清理资源,避免内存泄漏 onBeforeUnmount(() => { if (audioEl.value) { audioEl.value.removeEventListener("ended", playNextFile); audioEl.value.parentNode?.removeChild(audioEl.value); } }); function playNextFile() { currentFileIndex.value += 1; if (currentFileIndex.value === props.files.length) { audioEl.value.removeEventListener("ended", playNextFile); audioEl.value.parentNode?.removeChild(audioEl.value); return; } audioEl.value.src = props.files[currentFileIndex.value]; audioEl.value.play().catch(err => console.error("播放失败:", err)); } return { audioEl, playNextFile }; }, }; </script>
修复说明
- 将播放逻辑封装成
initPlay函数,初始化和更新时都能调用 - 用
watch监听props.files的变化,音频列表更新时自动重新播放 - 增加组件卸载时的资源清理逻辑,避免残留音频实例
- 给
play()方法添加错误捕获,处理浏览器自动播放限制等异常情况
内容的提问来源于stack exchange,提问作者Nopmd
相关产品推荐
相关产品推荐

