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

Vue.js中如何实现歌曲播放时seekbar进度条自动同步移动

Vue.js 音频播放器进度条自动更新修复方案

进度条无法自动跟随播放移动的核心原因是未监听音频实例的timeupdate事件,播放过程中当前播放时间变动时,没有同步更新Vue实例中绑定进度条宽度的progress响应式变量。同时原代码还存在API调用错误、事件重复绑定、时间显示未同步的问题,按以下步骤修改即可:


第一步:调整模板代码

给时间节点、进度条DOM增加ref引用,绑定进度条点击跳转事件,去掉不必要的jQuery依赖:

<div class="playbackBar">
    <span ref="currentTime" class="progressTime current">0:00</span>

    <div ref="progressBar" class="progressBar" @click="handleSeek">
        <div class="progressBarBg">
            <div :style="'width:'+progress+'%'" class="progress"></div>
        </div>
    </div>

    <span ref="remainingTime" class="progressTime remaining">0:00</span>
</div>

第二步:修复脚本逻辑

补全进度更新监听、修正错误API、优化事件绑定逻辑,修改后完整脚本如下:

<script>
export default {
    data(){
        return{
            current: {},
            index: 0,
            isPlaying: false,
            progress: 0,
            songs: [
                {
                    title: 'Sample',
                    artist: 'Sample Artist',
                    src: '/storage/audio/sample.mp3'
                }
            ],
            player: new Audio()
        }
    },
    methods: {
        // 秒数转 分:秒 格式工具方法
        formatTime(seconds) {
            if(isNaN(seconds)) return '0:00'
            const min = Math.floor(seconds / 60)
            const sec = Math.floor(seconds % 60).toString().padStart(2, '0')
            return `${min}:${sec}`
        },
        // 修复进度条点击跳转逻辑
        handleSeek(e) {
            const barWidth = this.$refs.progressBar.offsetWidth
            const percentage = e.offsetX / barWidth * 100
            // 修正原生Audio API:直接赋值currentTime属性实现跳转,不存在setTime方法
            this.player.currentTime = this.player.duration * (percentage / 100)
            this.progress = percentage
        },
        play(song){
            if(typeof song.src != "undefined"){
                this.current = song
                this.player.src = this.current.src
            }
           
            this.player.play()
            this.isPlaying = true;
        },
        pause(){
            this.player.pause();
            this.isPlaying = false;
        }
    },
    mounted() {
        // 核心:监听音频播放时间更新事件,同步进度条和时间显示
        this.player.addEventListener('timeupdate', () => {
            // 计算当前播放进度百分比
            this.progress = (this.player.currentTime / this.player.duration) * 100
            // 更新当前播放时间文本
            this.$refs.currentTime.textContent = this.formatTime(this.player.currentTime)
            // 更新剩余时间文本
            this.$refs.remainingTime.textContent = this.formatTime(this.player.duration - this.player.currentTime)
        })
        // 播放结束切歌事件只绑定一次,不要放在play方法里重复绑定
        this.player.addEventListener('ended', () => {
            this.index++;
            if (this.index > this.songs.length - 1) {
                this.index = 0;
            }
            this.current = this.songs[this.index];
            this.play(this.current);
        })
    },
    beforeUnmount() {
        // 组件销毁时释放音频资源,避免内存泄漏
        this.player.pause()
        this.player.src = ''
    },
    created(){
        this.current = this.songs[this.index];
        this.player.src = this.current.src;
    }
}
</script>

关键修复点说明

  • 核心进度更新:通过监听音频原生timeupdate事件(播放时每秒触发4~66次),实时计算进度百分比更新progress变量,驱动视图层进度条宽度变化
  • 修正API错误:原生Audio实例跳转播放位置直接修改currentTime属性即可,不存在setTime方法;定义的player本身就是Audio实例,没有player.audio的嵌套属性
  • 修复事件泄漏:将ended切歌监听从play方法移到挂载生命周期,全局只绑定一次,避免每次播放新增重复监听
  • 补全时间联动:进度更新时同步刷新两侧的播放时间、剩余时间文本
  • 移除jQuery依赖:通过Vue原生ref获取DOM元素计算点击位置,更符合框架开发规范
  • 增加资源清理:组件销毁时暂停播放、释放音频资源,避免内存泄漏

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 05:39:14