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

Vue.js实现获取DOM音频元素并播放时play方法报错

报错核心原因
  • HTML标准中id属性是页面全局唯一值,你给同组的<button>和<audio>元素绑定了完全相同的id,document.getElementById()只会返回DOM树中第一个匹配id的元素,也就是你点击的按钮本身,按钮元素不存在play()方法,调用必然抛出错误。
  • 额外问题:方法声明了形参e却未使用,直接依赖全局event对象存在兼容性风险;Vue项目中直接用原生API操作DOM不是推荐做法,稳定性弱于框架提供的元素获取方式。
修复实现(符合Vue开发规范)

直接通过ref获取音频元素,不需要依赖id匹配,同时可以顺手处理多音频同时播放的冲突问题,代码如下:

<script>
export default {
  data() {
    return {
      // 原有cover_xl、title、preview字段保持不变即可
    };
  },
  methods: {
    play_audio(index) {
      const currentAudio = this.$refs.audioList[index];
      // 可选逻辑:播放当前音频前暂停其他所有音频,避免声音重叠
      this.$refs.audioList.forEach(audio => {
        if (audio !== currentAudio && !audio.paused) {
          audio.pause();
          audio.currentTime = 0;
        }
      });
      // 捕获播放异常(比如浏览器自动播放限制导致的播放失败),避免控制台报错
      currentAudio.play().catch(err => {
        console.warn('音频播放失败:', err);
      });
    },
  },
};
</script>

<template>
  <main>
    <div class="results">
      <!-- v-for必须绑定key,这里用index做key仅作示例,有唯一id优先用唯一id -->
      <div class="result" v-for="(item, index) in cover_xl" :key="index">
        <div class="result_img">
          <img :src="cover_xl[index]" :alt="title[index]" />
          <!-- 点击时直接传入当前循环的索引,不需要给按钮绑定id -->
          <button @click="play_audio(index)">Play</button>
        </div>
        <h2>{{ title[index] }}</h2>
        <!-- v-for下绑定同名ref,会自动收集为对应顺序的元素数组 -->
        <audio ref="audioList">
          <source :src="preview[index]" />
        </audio>
      </div>
    </div>
  </main>
</template>
最小改动方案(不推荐长期使用)

如果不想调整原有代码结构,只需要保证按钮和音频的id不重复即可:

  • 给audio标签的id加固定前缀:<audio :id="'audio_'+preview[index]">
  • 点击获取元素时拼接对应前缀:document.getElementById('audio_'+button).play()

这种方式依然是原生DOM操作,不符合Vue的设计理念,仅适合临时快速修复。

内容的提问来源于stack exchange,提问作者M123456

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 19:57:15