Vue 3 中用 watch 监听音视频进度需分离驱动源与响应目标:以 video.currentTime 为唯一可信源,进度条只读不写;拖拽时暂停监听,seeked 后恢复;结合 duration 计算百分比并防 NaN;失焦或暂停时抑制更新。

用 Vue 3 的 watch 监听音视频播放进度并同步进度条,关键在于**分离“驱动源”和“响应目标”**:播放器 DOM 的 currentTime 是唯一可信源,进度条只读取、不反向控制;同时要规避拖拽与自动播放之间的数据冲突。
监听 video.currentTime 变化并更新进度条值
进度条(如 <input type="range">)应绑定一个响应式变量(如 progressValue),但这个变量不能靠双向绑定(v-model)直接连 video.currentTime,否则会形成干扰闭环。
- 在
onMounted后获取videoRef,确保 DOM 已挂载 - 使用
watch监听videoRef.value?.currentTime,需加空值检查和防 NaN 处理 - 回调中更新
progressValue.value = Math.round(videoRef.value?.currentTime || 0),避免小数抖动 - 添加
flush: 'post'选项,确保 DOM 更新后才触发,便于后续尺寸/样式处理
进度条拖动时暂停自动同步,手动跳转后恢复
用户拖动进度条属于“主动控制”,此时应临时停掉对 currentTime 的监听,防止播放器自动推进覆盖用户选择。
Vue 3 组合式 API 与 最佳实践,涵盖代码组织、useXxx 模式、组合式函数设计、Store 集成、响应式优化及功能抽取。
- 调用
watch返回的停止函数(如stopWatch())在@input或@change事件中暂停监听 - 设置
videoRef.value.currentTime = newTime,并手动调用play()(如需) - 监听
videoRef的seeked事件,在跳转完成后再重新启用watch - 可配合
ref标记当前是否处于“手动拖拽态”,避免误判
结合 duration 实现百分比进度显示
仅同步数值不够直观,进度条通常需百分比(value / duration * 100)。但 duration 初始为 NaN,需等待加载就绪。
立即学习“前端免费学习笔记(深入)”;
- 监听
videoRef.value?.duration变化,或使用@loadedmetadata事件作为初始化时机 - 定义计算属性
computed(() => (progressValue.value / (duration.value || 1)) * 100),安全除法防报错 - 将该计算值绑定到进度条的
:max和:value(若用 range input)或 CSS width(若自绘进度条)
处理页面失焦与暂停状态下的同步抑制
用户切走标签页、视频暂停、或静音缓冲时,不应继续上报或更新进度条,否则造成视觉跳变或逻辑错乱。
- 监听
document.hidden,失焦时暂停watch,恢复可见时校准一次(对比服务端或重读currentTime) - 监听
videoRef的pause和playing事件,暂停时不触发watch回调(可用标志位控制) - 在
timeupdate事件中加判断:if (videoRef.value?.paused) return,从源头减少无效触发

















