Vue.js音频播放器开发:Quasar滑块同步与暂停异常问题
解决Vue+Quasar音频播放器滑块实时更新与暂停卡顿问题
问题根源
你当前代码的核心问题是playAudio函数里的同步while循环,它会持续占用浏览器主线程,导致UI完全卡顿,无法响应暂停点击;同时循环里的curremtTime是拼写错误(应为currentTime),这也会导致进度更新失效。
解决方案
改用异步定时器来更新滑块进度,同时维护定时器引用,在暂停/音频结束时清除定时器,避免无效循环。另外需要监听音频加载事件获取正确时长,修正播放/暂停的逻辑判断。
修改后的完整代码
<template> <div style="min-height: 667px; overflow-y: scroll"> <div class="bg-white flex flex-center" style="min-height: 40vh"> <div class="absolute" style="width: 100%; max-width: 500px"> <h3 class="text-center text-h4 text-primary text-weight-bold"> WITHOUT VOCALS </h3> <div class="full-width flex flex-center"> <q-btn flat round color="secondary" text-color="primary" icon="fa-solid fa-backward" class="q-ma-md" size="20px" /> <q-btn flat round color="secondary" text-color="primary" :icon="vocalPlayIcon" size="30px" class="bg-secondary q-ma-md" @click="toggleAudioWithoutVocals()" /> <q-btn flat round color="secondary" text-color="primary" icon="fa-solid fa-forward" class="q-ma-md" size="20px" /> <audio style="display: none" id="audio-player-without-vocals" controls > <source src="~assets/audio/shinedown.mp3" type="audio/mpeg" /> Your browser does not support the audio tag. </audio> </div> <div class="full-width" style="max-width: 800px"> <q-slider v-model="vocalPlayTime" :min="0" :max="vocalAudioDuration" @input="seekAudio" /> </div> </div> </div> </div> </template> <script setup> import { ref, onMounted, onUnmounted } from "vue"; const vocalPlayIcon = ref("fa-solid fa-play"); const vocalPlayTime = ref(0); const vocalAudioDuration = ref(0); const vocalAudioObj = ref(null); const progressTimer = ref(null); // 保存定时器ID onMounted(() => { vocalAudioObj.value = document.getElementById("audio-player-without-vocals"); // 监听音频加载完成事件,获取准确时长 vocalAudioObj.value.addEventListener("loadedmetadata", () => { vocalAudioDuration.value = vocalAudioObj.value.duration; }); // 监听音频结束事件,自动重置播放状态 vocalAudioObj.value.addEventListener("ended", () => { clearInterval(progressTimer.value); vocalPlayIcon.value = "fa-solid fa-play"; vocalPlayTime.value = 0; }); }); onUnmounted(() => { // 组件销毁时清除定时器,避免内存泄漏 if (progressTimer.value) { clearInterval(progressTimer.value); } }); const toggleAudioWithoutVocals = () => { if (vocalAudioObj.value.paused) { startPlay(); } else { pausePlay(); } }; // 开始播放逻辑 const startPlay = () => { vocalPlayIcon.value = "fa-solid fa-pause"; vocalAudioObj.value.play(); // 启动定时器,每隔100ms更新进度(可根据需求调整间隔) progressTimer.value = setInterval(() => { vocalPlayTime.value = vocalAudioObj.value.currentTime; }, 100); }; // 暂停播放逻辑 const pausePlay = () => { vocalAudioObj.value.pause(); vocalPlayIcon.value = "fa-solid fa-play"; // 清除定时器,停止进度更新 clearInterval(progressTimer.value); }; // 滑块拖动跳转音频位置 const seekAudio = () => { vocalAudioObj.value.currentTime = vocalPlayTime.value; }; </script>
关键改动说明
- 移除阻塞主线程的
while循环,改用setInterval异步更新滑块进度,彻底解决浏览器卡顿问题。 - 添加
progressTimer引用,用于在暂停/音频结束时清除定时器,精准停止进度更新。 - 监听音频
loadedmetadata事件获取正确时长,解决初始时长为NaN的问题。 - 监听音频
ended事件,自动重置播放状态和滑块位置,提升用户体验。 - 新增滑块拖动跳转功能(
seekAudio),支持手动调整播放位置。 - 组件销毁时清除定时器,避免内存泄漏。
- 修正原代码中
curremtTime的拼写错误。
内容的提问来源于stack exchange,提问作者Qiuzman
相关产品推荐
相关产品推荐

