更新记录
1.0.0(2026-09-01) 下载此版本
- 初始化
平台兼容性
uni-app(4.62)
| Vue2 | Vue2插件版本 | Vue3 | Vue3插件版本 | Chrome | Safari | app-vue | app-vue插件版本 | app-nvue | Android | Android插件版本 | iOS | iOS插件版本 | 鸿蒙 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| √ | 1.0.0 | √ | 1.0.0 | √ | √ | √ | 1.0.0 | - | 5.0 | 1.0.0 | 12 | 1.0.0 | - |
| 微信小程序 | 微信小程序插件版本 | 支付宝小程序 | 支付宝小程序插件版本 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 小红书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| √ | 1.0.0 | √ | 1.0.0 | - | - | - | - | - | - | - | - | - | - |
uni-app x(4.62)
| Chrome | Safari | Android | Android插件版本 | iOS | iOS插件版本 | 鸿蒙 | 微信小程序 |
|---|---|---|---|---|---|---|---|
| - | - | 5.0 | 1.0.0 | 12 | 1.0.0 | - | √ |
dyl-video-swiper 短视频滑动播放组件
dyl-video-swiper 是适配 uni-app Vue 3 和 uni-app x / UVue 的竖向短视频流组件。组件仅维护 3 个 swiper-item,循环复用上一条、当前条和下一条视频,避免一次性创建完整视频列表。
使用方式
组件符合 easycom 目录规范,Vue 3 和 UVue 使用相同的模板 API,可直接使用。
uni-app x / UVue
<template>
<view class="page">
<dyl-video-swiper
class="video-feed"
:video-list="videoList"
:autoplay="true"
:muted="false"
:controls="false"
:loop="true"
:auto-change="false"
:loading="loadingMore"
:has-more="hasMore"
@change="handleVideoChange"
@loadMore="handleLoadMore"
@error="handleVideoError"
>
<template #default="{ item }">
<view class="video-info">
<text class="video-title">{{ item.src }}</text>
</view>
</template>
</dyl-video-swiper>
</view>
</template>
<script setup lang="uts">
import {
DylVideoSwiperChangeEvent,
DylVideoSwiperErrorEvent,
DylVideoSwiperItem,
DylVideoSwiperLoadMoreEvent
} from '@/uni_modules/dyl-video-swiper/components/dyl-video-swiper/types.uts'
const videoList = ref<DylVideoSwiperItem[]>([
{
src: 'https://example.com/video-1.mp4',
poster: 'https://example.com/poster-1.jpg',
objectFit: 'cover'
},
{
src: 'https://example.com/video-2.mp4',
poster: 'https://example.com/poster-2.jpg',
objectFit: 'contain'
}
])
const loadingMore = ref<boolean>(false)
const hasMore = ref<boolean>(true)
function handleVideoChange(event : DylVideoSwiperChangeEvent) : void {
console.log('当前视频下标:' + event.index)
}
function handleLoadMore(event : DylVideoSwiperLoadMoreEvent) : void {
if (loadingMore.value == true || hasMore.value == false) {
return
}
console.log('触发加载:' + event.currentIndex + '/' + event.total)
loadingMore.value = true
// 请求完成后替换或 push 到 videoList,并将 loadingMore 设回 false。
}
function handleVideoError(event : DylVideoSwiperErrorEvent) : void {
console.log('视频播放失败,下标:' + event.index)
}
</script>
<style>
.page {
flex: 1;
background-color: #000000;
}
.video-feed {
flex: 1;
}
.video-info {
position: absolute;
left: 16px;
right: 16px;
bottom: 48px;
}
.video-title {
font-size: 16px;
color: #ffffff;
}
</style>
组件高度为
100%,父容器必须提供明确高度或flex: 1。
uni-app Vue 3
Vue 3 版本的模板、Props 和事件监听方式与上面的 UVue 示例一致,script 使用 TypeScript,并从 Vue 组件导入对应类型:
<script setup lang="ts">
import { ref } from 'vue'
import type {
DylVideoSwiperChangeEvent,
DylVideoSwiperErrorEvent,
DylVideoSwiperItem,
DylVideoSwiperLoadMoreEvent
} from '@/uni_modules/dyl-video-swiper/components/dyl-video-swiper/dyl-video-swiper.vue'
const videoList = ref<DylVideoSwiperItem[]>([
{
src: 'https://example.com/video-1.mp4',
poster: 'https://example.com/poster-1.jpg',
objectFit: 'cover',
data: {
title: '示例视频'
}
}
])
const loadingMore = ref<boolean>(false)
const hasMore = ref<boolean>(true)
function handleVideoChange(event: DylVideoSwiperChangeEvent): void {
console.log('当前视频下标:' + event.index)
}
function handleLoadMore(event: DylVideoSwiperLoadMoreEvent): void {
if (loadingMore.value || !hasMore.value) {
return
}
console.log('触发加载:' + event.currentIndex + '/' + event.total)
loadingMore.value = true
// 请求完成后替换或 push 到 videoList,并将 loadingMore 设回 false。
}
function handleVideoError(event: DylVideoSwiperErrorEvent): void {
console.log('视频播放失败,下标:' + event.index)
}
</script>
数据结构
UVue:
type DylVideoSwiperItem = {
src : string;
poster ?: string;
objectFit ?: string;
data ?: UTSJSONObject;
}
Vue 3:
type DylVideoSwiperItem = {
src: string
poster?: string
objectFit?: string
data?: Record<string, unknown>
}
| 字段 | 必填 | 说明 |
|---|---|---|
src |
是 | 视频地址,空地址会被过滤。 |
poster |
否 | 视频首帧加载前及相邻槽位显示的海报。 |
objectFit |
否 | 支持 contain、cover、fill,非法值按 contain 处理。 |
data |
否 | 传递给插槽的自定义业务数据。 |
组件不会克隆或裁剪 item 字段,因此插槽可以读取原始 item 数据。
Props
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
videoList |
DylVideoSwiperItem[] |
[] |
视频列表,支持替换数组和原地 push。 |
autoplay |
boolean |
true |
切换后是否自动播放。 |
muted |
boolean |
false |
是否静音;Web 端需要无手势自动播放时建议设为 true。 |
controls |
boolean |
false |
是否显示原生控制栏。开启后不会创建全屏自定义点击层。 |
clickToPlay |
boolean |
true |
controls=false 时,点击画面是否切换播放/暂停。 |
loop |
boolean |
true |
是否循环播放单条视频。 |
autoChange |
boolean |
false |
播放结束后是否切换下一条;开启时组件自动关闭单视频 loop。 |
showLoading |
boolean |
true |
是否显示视频加载提示。 |
loadMoreOffsetCount |
number |
2 |
距离尾部多少条时触发加载更多。 |
loading |
boolean |
false |
外部是否正在加载,防止重复触发。 |
hasMore |
boolean |
true |
是否还有更多数据。 |
Events
| 事件 | 参数 | 说明 |
|---|---|---|
change |
DylVideoSwiperChangeEvent |
初始化、手动定位或当前源数据项切换时触发。 |
loadMore |
DylVideoSwiperLoadMoreEvent |
到达加载阈值且未在加载时触发。 |
error |
DylVideoSwiperErrorEvent |
当前视频播放失败,包含下标、item 和原始错误事件。 |
play |
UniEvent / 平台原始事件 |
当前视频实际开始播放。 |
pause |
UniEvent / 平台原始事件 |
当前视频实际暂停。 |
ended |
UniEvent / 平台原始事件 |
当前视频播放结束。 |
controlstoggle |
UniVideoControlsToggleEvent / 平台原始事件 |
当前视频原生控制栏状态变化。 |
click |
UniPointerEvent / 平台原始事件 |
当前视频区域被点击。 |
同一列表长度只会自动触发一次 loadMore。加载失败时,将 loading 从 true 设回 false 后即可再次触发;加载成功后列表长度变化会自动进入下一轮判断。
表中的 UniEvent、UniPointerEvent 和 UniVideoControlsToggleEvent 是 UVue 类型;Vue 3 版本传递对应平台的视频组件原始事件。DylVideoSwiperErrorEvent.event 同样保存对应平台的原始错误事件。
Slot
默认插槽向每个复用槽位传递 item:
<dyl-video-swiper :video-list="videoList">
<template #default="{ item }">
<view class="overlay">
<text class="title">{{ item.src }}</text>
</view>
</template>
</dyl-video-swiper>
插槽可放标题、作者和操作按钮。纯展示且覆盖全屏的插槽根节点建议设置 pointer-events: none,否则会拦截组件的点击播放手势;需要交互的按钮可放在较小的独立区域。
Expose
组件暴露以下方法:
initSwiperData(targetOriginIndex : number = -1) : void
playCurrentVideo() : void
pauseCurrentVideo() : void
调用公开方法前,需要为组件设置模板引用:
<dyl-video-swiper ref="swiperRef" :video-list="videoList" />
UVue 通过组件实例的 $callMethod 调用:
import type { ComponentPublicInstance } from 'vue'
const swiperRef = ref<ComponentPublicInstance | null>(null)
function pauseVideoOnLeave() : void {
if (swiperRef.value != null) {
swiperRef.value.$callMethod('pauseCurrentVideo')
}
}
Vue 3 可以直接调用 defineExpose 暴露的方法:
type DylVideoSwiperInstance = {
initSwiperData: (targetOriginIndex?: number) => void
playCurrentVideo: () => void
pauseCurrentVideo: () => void
}
const swiperRef = ref<DylVideoSwiperInstance | null>(null)
function pauseVideoOnLeave(): void {
swiperRef.value?.pauseCurrentVideo()
}
行为说明
- 列表变更会重新映射 3 个槽位;当前视频地址没有变化时不会中断播放。
- 当前视频地址发生变化时会停止旧视频并按
autoplay重新准备播放。 - 播放状态由
play、pause、ended、error等真实事件校正。 - 海报填充模式会跟随视频的
objectFit。 - 页面进入后台时组件不会自动感知页面生命周期,页面应在
onHide/onUnload中调用pauseCurrentVideo。
参考与致谢
本组件借鉴了 akFace 的作品《仿抖音短视频小程序 APP 组件(超高性能)自动预加载》,感谢原作者的思路与分享。

收藏人数:
下载插件并导入HBuilderX
赞赏(0)
下载 97
赞赏 0
下载 12549057
赞赏 1947
赞赏
京公网安备:11010802035340号