更新记录

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 支持 containcoverfill,非法值按 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。加载失败时,将 loadingtrue 设回 false 后即可再次触发;加载成功后列表长度变化会自动进入下一轮判断。

表中的 UniEventUniPointerEventUniVideoControlsToggleEvent 是 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 重新准备播放。
  • 播放状态由 playpauseendederror 等真实事件校正。
  • 海报填充模式会跟随视频的 objectFit
  • 页面进入后台时组件不会自动感知页面生命周期,页面应在 onHide / onUnload 中调用 pauseCurrentVideo

参考与致谢

本组件借鉴了 akFace 的作品《仿抖音短视频小程序 APP 组件(超高性能)自动预加载》,感谢原作者的思路与分享。

隐私、权限声明

1. 本插件需要申请的系统权限列表:

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

许可协议

MIT协议

暂无用户评论。