You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue.js周期性播放音频问题:仅刷新时播放,需改为每15秒自动播放

解决Vue.js每15秒自动播放更新音频的问题

核心问题分析

你的代码主要有两个关键问题导致无法周期性自动播放:

  1. 父组件中错误地将computed对象赋值给ref的value,破坏了响应式更新逻辑
  2. 子组件仅在初始化时播放音频,未监听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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 11:05:15