最可行起点是swiper+vertical="true",但真机卡顿黑屏源于video实例管理、平台策略适配与生命周期控制不到位;需规避@change中直接play()、ios延迟、动态列表越界等问题,严格遵循静音、playsinline、预加载、资源释放及cover-view遮罩等规范。

直接用 swiper + vertical="true" 是最可行的起点,但真机上卡顿、黑屏、自动播放失败不是 swiper 本身的问题,而是 video 实例管理、平台策略适配和生命周期控制没到位。
swiper 的 @change 事件不是实时滚动信号,别在它里面直接 play()
很多人以为 @change 能捕获滑动过程中的每一帧,其实它只在 swiper 完全停止、当前项完全对齐后才触发。这意味着:
- 不能在
onSwiperChange里直接调this.$refs.video.play(),DOM 可能还没渲染完,得包一层this.$nextTick - iOS 上
current更新有微小延迟,别拿它算进度条或做动画同步 - 如果视频列表是动态追加的,更新
videoList后必须手动重置currentIndex,否则容易越界或卡死在空白页 - 安卓和 H5 下响应及时;iOS 微信 WebView 中可能合并多次快速滑动,只触发一次
@change
video 必须静音 + playsinline 才能在 iOS 和小程序里不强制全屏
首屏视频不设 muted="true" + :autoplay="true",iOS Safari 和微信 WebView 就不会出画面——这是系统级限制,不是 bug。
- 所有
video标签必须同时带playsinline、webkit-playsinline、x5-playsinline,缺一不可 -
抖音小程序要求
enable-danmu="false",否则首帧黑屏 - H5 端首次加载后,必须等用户触发一次
touchstart,后续play()才真正可用 - 监听
@loadedmetadata或@canplay,再尝试开声(videoContext.mute(false)),但部分机型仍需用户点一下屏幕
别一次性挂 100 个 video 标签,内存爆炸就发生在你滑到第 50 条时
“全量渲染”是抖音式视频流最常踩的坑。浏览器对大量 video 标签的解码压力是硬性天花板。
- 只保留
current - 1、current、current + 1共 3 个video实例,其余用v-if="false"彻底移除 DOM - 每个
video加preload="metadata",而非"auto",避免并发加载阻塞主线程 - 滑出视口 500ms 后,调用
pause()+src = ''+load()释放资源 - 小程序中慎用
autoplay="true",设为false,等@loadedmetadata触发后再play()
小程序里 touchmove 在 video 区域不生效?那是 cover-view 没盖对
微信小程序的 video 是原生组件,层级高于所有 webview 内容,touchstart/move 事件根本无法穿透。这不是 bug,是设计。
- 必须用
cover-view盖一层透明遮罩,把滑动事件抢过来 - 遮罩要覆盖整个视频区域,且
z-index高于video(小程序中cover-view层级最高) - App 端必须改用
nvue页面 + 原生video组件,才能完整捕获touch事件并支持gestureConfig - 切换前调
this.$refs.video.pause(),切换后this.$refs.nextVideo.play(),中间不能有空档
真正难的不是怎么滑,而是「什么时候销毁、什么时候预加载、什么时候强制暂停」——这些边界点稍有偏差,用户划着划着就卡住或黑屏了。尤其是 iOS 微信和抖音小程序,它们对 autoplay 的策略细节差异极大,必须分平台写逻辑,不能靠一个配置打天下。











