uni-app video组件不支持原生自动连播,需手动监听ended事件、校验状态、等待canplay后调用play(),且iOS和小程序因静音策略限制必须由用户首次点击触发。

uni-app 中 video 组件不支持原生“自动播放下一个”功能
uni-app 的 video 组件底层映射到各端原生控件(iOS/Android/小程序),但没有提供类似 autoplayNext 或 playlist 的属性。所谓“连播”,必须手动监听播放结束事件、主动切换 src 并调用 play() —— 而且各端行为差异极大,尤其 iOS 和微信小程序对自动播放限制极严。
监听 ended 事件后切换视频要加防抖和状态校验
直接在 @ended 里写 this.currentSrc = nextUrl; this.$nextTick(() => this.$refs.video.play()) 很容易失败:iOS 微信中 play() 会被静音拦截;App 端可能因资源未加载完而报错 DOMException: The element has no supported sources;多个 ended 可能被重复触发(尤其列表快速切换时)。
- 必须用
data中的布尔变量(如isPlaying)标记当前是否处于有效播放态,@ended触发前先判断if (!this.isPlaying) return - 切换
src后不能立刻play(),需等@loadedmetadata或@canplay回调再执行,否则 H5 和 App 端大概率失败 - 微信小程序需额外处理:
play()必须由用户手势触发,所以“连播”在小程序里本质不可行——只能靠 UI 引导用户点一次“继续播放”按钮
循环逻辑要区分“单个视频循环”和“列表循环”,配置方式完全不同
video 组件的 loop 属性只控制当前视频是否重复播放,和“列表循环”无关。列表循环需要自己维护索引和边界条件。
- 单个视频循环:直接设
:loop="true",无需 JS 干预 - 列表循环(播完最后一个再播第一个):在
@ended中计算nextIndex = (currentIndex + 1) % list.length,然后更新currentSrc和currentIndex - 非循环列表(播完停止):检查
currentIndex === list.length - 1,满足则清空currentSrc或显示提示 - 注意:H5 端若用
v-for渲染多个video标签并复用 ref,会导致 ref 指向错误——必须用动态 ref(如:ref="'video' + index")或只保留一个video标签反复更新src
真机调试时 iOS 和小程序的静音策略是最大障碍
无论你逻辑写得多严谨,iOS Safari、微信、支付宝小程序都会阻止无用户交互的 play() 调用,表现为静音、黑屏或直接报错 NotAllowedError: play() can only be initiated by a user gesture。这不是 bug,是策略。
- 唯一可靠解法:首次播放必须由用户点击触发(比如“播放”按钮),之后的连播才能通过
@ended+@canplay链式调用实现 - App 端(iOS/Android)相对宽松,但 iOS 上仍建议首次播放也走用户点击,避免审核风险
- 不要依赖
autoplay属性——它在多数环境默认失效,且与连播逻辑冲突 - 测试时务必真机验证,模拟器和 H5 页面的播放行为会严重误导判断
实际连播逻辑最易忽略的是「加载状态同步」:src 切换后,组件不会立即进入 canplay 状态,中间存在空白期。这个间隙如果用户误点暂停或进度条,后续状态就全乱了。得把 loading、canplay、playing、ended 几个状态用 data 显式管理,而不是只靠事件回调跳转。


















