实现视频播放进度同步的关键是统一响应式数据源(如Vue的ref或React的自定义Hook)并双向驱动,各组件只读不写,通过事件委托更新,配合防抖、就绪校验和跨端同步兜底。

用响应式状态实现视频播放进度同步,核心是让多个组件共享并响应同一个播放时间点(currentTime),同时避免各自维护独立状态导致不同步。关键不在于“监听事件”,而在于“统一数据源 + 双向驱动”。
用 ref 或 reactive 管理共享的 currentTime
不要在每个组件里单独定义 currentTime,而是创建一个跨组件可访问的响应式对象:
- Vue 中推荐用
ref(适合单值)或reactive({ time: 0 }),配合provide/inject或 Pinia/Vuex 全局管理 - React 中可用
useRef+useEffect手动同步,但更推荐useState配合自定义 Hook(如useVideoSync)封装共享逻辑 - 示例(Vue):在父组件中定义
const videoTime = ref(0),再通过provide('videoTime', videoTime)注入子组件
播放器组件主动更新状态,并触发同步
原生 <video></video> 元素本身不自动响应外部 currentTime 变化,需手动绑定与监听:
- 用
v-model:currentTime(Vue 3.4+)或:currentTime.sync(旧版)实现双向绑定;否则需监听timeupdate事件更新 ref,并在 ref 变化时调用video.currentTime = value - 务必加防抖(如
throttle30ms),避免高频更新拖慢渲染 - 注意:设置
currentTime后可能触发seeking和seeked,应忽略这些事件中的重复赋值,防止死循环
进度条、字幕、时间轴等组件只读取、不修改状态
所有非控制类组件(如进度滑块显示、字幕定位、章节高亮)应仅响应 videoTime 变化,禁止直接操作 DOM 或修改时间:
- 进度条组件用
v-bind:value="videoTime"显示位置,点击拖动时只触发emit('seek', newTime),由播放器组件统一处理 - 字幕组件根据
videoTime查找当前 active 的字幕项,用computed缓存结果,避免每次重算 - 若需“点击字幕跳转”,同样只发事件,不直接改
currentTime
处理异步加载、暂停/恢复和跨设备一致性
真实场景中,视频可能未就绪、被暂停、或用户在多端切换,需额外兜底:
- 监听
loadedmetadata后才开始同步,避免初始化时currentTime为 NaN - 暂停时记录最后时间,恢复播放前校验当前
videoTime是否匹配video.currentTime,不一致则手动修正 - 如需多端同步(如 Web + 小程序),需将
videoTime上报服务端,并用 WebSocket 或定时拉取保持各端一致

















