更新记录

0.0.1(2026-06-06)

新增

  • 基于固定缓冲 + 滑动窗口回收算法的短视频滑动切换组件
  • 支持 bufferCount 配置缓冲区数量(3/5/7 等)
  • 支持 circular 首尾衔接循环滑动
  • 支持 autoReplay 视频自动重播
  • 支持 autoChange 播放结束自动切换
  • 支持 autoObjectFit 根据宽高比自动设置 object-fit
  • 支持 disableSwipe 禁止滑动切换(评论区场景)
  • 支持 cacheProgress 缓存播放进度,切回从上次位置继续
  • 支持 playbackRate 初始播放速率 + setPlaybackRate 动态设置倍速
  • 支持 longPressSpeed 长按加速播放,slot 导出 isLongPressSpeedUp 状态
  • 支持 shortSwipes / swipeDelay / swipeAwaitAnimation 滑动手势精细控制
  • 支持 srcKey / posterKey / objectFitKey / titleKey 自定义字段映射
  • 支持 lClassVideo / lClassProgress 外部样式类
  • 支持 load 事件实现无限加载
  • 支持通过 ref 暴露 jumpToVideo / togglePlay / toggleMuted / playSeeked / pause / resume / setPlaybackRate / getCurrentIndex / getMuted / startLongPressSpeedUp / endLongPressSpeedUp 方法
  • 支持 default 插槽自定义浮层,导出 item / index / isCurrent / playing / isLongPressSpeedUp / currentTime / duration / progressPercent / formatTime
  • 内置底部进度条,支持点击跳转
  • 完善的错误重试机制,每个视频独立维护错误计数
  • UTS 类型完备,全部使用原生事件类型
  • 包含抖音风格 demo(点赞、评论、倍速、选集等功能示例)

平台兼容性

uni-app(5.07)

Vue2 Vue3 Chrome Safari app-vue app-nvue Android iOS 鸿蒙
- -
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 小红书小程序 快应用-华为 快应用-联盟
- - - - - - - - - - -

uni-app x(5.07)

Chrome Safari Android iOS 鸿蒙 微信小程序

lime-video-swiper 短视频滑动组件

一个高性能的短视频滑动切换组件,基于固定缓冲 + 滑动窗口回收算法,提供丝滑的上下滑动体验。适用于抖音/TikTok 风格的短视频 Feed 流、剧集列表等场景。

本组件只负责视频滑动切换,不包含任何 UI。 组件本身没有点赞、评论、分享、头像等界面元素,如需实现抖音等短视频 UI 效果,请通过 default 插槽自行实现浮层界面。

插件依赖:lime-shared

安装方法

  1. 在 uni-app 插件市场中搜索并导入 lime-video-swiper
  2. 导入后可能需要重新编译项目
  3. 在页面中使用 l-video-swiper 组件

代码演示

基础用法

最简单的用法,传入视频列表即可自动播放和滑动切换。

<l-video-swiper
  :videoList="videoList"
  :autoplay="true"
  :autoObjectFit="true"
  @change="onChange"
  @load="onLoadMore"
/>
const videoList = ref([
  { src: 'https://example.com/video1.mp4', poster: 'https://example.com/cover1.jpg' },
  { src: 'https://example.com/video2.mp4', poster: 'https://example.com/cover2.jpg' },
  { src: 'https://example.com/video3.mp4', poster: 'https://example.com/cover3.jpg' }
]);

自定义浮层(点赞、评论等)

通过 default 插槽实现抖音风格的 UI 浮层,使用 isCurrent 控制当前项的显隐。

<l-video-swiper :videoList="videoList">
  <template #default="{ item, index, isCurrent }">
    <view class="overlay" :style="{ opacity: isCurrent ? 1 : 0 }">
      <!-- 右侧操作栏 -->
      <view class="sidebar">
        <view class="sidebar-item" @click.stop="toggleLike(item)">
          <image class="icon" :src="liked ? 'heart-filled.svg' : 'heart.svg'" />
          <text class="count">{{ item.likeCount }}</text>
        </view>
        <view class="sidebar-item" @click.stop="openComment(item)">
          <image class="icon" src="comment.svg" />
          <text class="count">{{ item.commentCount }}</text>
        </view>
      </view>
      <!-- 底部信息 -->
      <view class="info">
        <text class="author">@{{ item.author }}</text>
        <text class="desc">{{ item.desc }}</text>
      </view>
    </view>
  </template>
</l-video-swiper>

连续点击点赞

连续快速点击视频时触发 doubleClick 事件(300ms 内第 2 次及以上点击),参数包含 clickCount(连续点击次数),可用于实现抖音式连续点赞动画。爱心动画建议放在视频区全局覆盖层(而非 slot 内),避免跟随视频项切换。

<view class="video-area">
  <l-video-swiper :videoList="videoList" @doubleClick="onDoubleClick">
    <template #default="{ item, isCurrent }">
      <!-- 浮层内容 -->
    </template>
  </l-video-swiper>
  <!-- 爱心动画(全局覆盖层,不放在 slot 内) -->
  <view v-if="showHeart" :key="heartKey" class="heart-anim heart-anim--active">
    <text class="heart-icon">&#x2764;</text>
  </view>
</view>
const showHeart = ref(false);
const heartKey = ref(0);
let heartTimer: number|null = null;

const onDoubleClick = (detail) => {
  // 连续点击点赞逻辑,detail.clickCount 为连续点击次数
  heartKey.value++; // 递增 key 强制重建元素,CSS animation 从头播放
  showHeart.value = true;
  if (heartTimer != null) clearTimeout(heartTimer!);
  heartTimer = setTimeout(() => { showHeart.value = false; heartTimer = null; }, 800);
};

下拉刷新

在第一个视频继续下拉时触发 refresh 事件,替换 videoList 即可自动重新初始化。

<l-video-swiper
  ref="swiperRef"
  :videoList="videoList"
  @refresh="onRefresh"
/>
const swiperRef = ref<LVideoSwiperComponentPublicInstance|null>(null);

const onRefresh = () => {
  const newList = fetchNewData();
  videoList.value = newList;
};

评论区 + 禁止滑动

打开评论区时设置 disableSwipe 禁止滑动切换,clickToggle=false 禁止点击切换播放状态,监听 click 事件关闭评论区。

<l-video-swiper
  :videoList="videoList"
  :disableSwipe="showComment"
  :clickToggle="!showComment"
  @click="onSwiperClick"
  @change="onChange"
>
  <template #default="{ item, isCurrent }">
    <!-- 浮层内容 -->
  </template>
</l-video-swiper>

<!-- 评论区 -->
<view class="comment-panel" :class="{ 'comment-panel--visible': showComment }">
  <text>评论区</text>
</view>
const showComment = ref(false);

const openComment = () => { showComment.value = true; };
const closeComment = () => { showComment.value = false; };

// clickToggle=false 时点击只派发 click 事件,不切换播放状态
const onSwiperClick = () => {
  if (showComment.value) closeComment();
};

const onChange = () => {
  // 切换视频时关闭评论区
  if (showComment.value) showComment.value = false;
};

播放倍速控制

通过 ref 调用 setPlaybackRate 动态设置播放速率,切换视频后倍速自动保持。

<l-video-swiper ref="swiperRef" :videoList="videoList" />

<!-- 倍速选择面板 -->
<view class="rate-panel" v-if="showRatePanel">
  <view v-for="rate in [0.5, 0.75, 1.0, 1.25, 1.5, 2.0]" :key="rate"
    @click="onSetRate(rate)">
    <text>{{ rate === 1.0 ? '正常' : rate + 'x' }}</text>
  </view>
</view>
const swiperRef = ref<LVideoSwiperComponentPublicInstance|null>(null);
const showRatePanel = ref(false);

const onSetRate = (rate: number) => {
  swiperRef.value!.setPlaybackRate(rate);
  showRatePanel.value = false;
};

长按加速播放

长按视频时加速播放(类似抖音长按快进),松开后恢复原速。通过 longPressSpeed 设置加速倍率,slot 中的 isLongPressSpeedUp 可用于显示加速提示。

<l-video-swiper :videoList="videoList" :longPressSpeed="2.0">
  <template #default="{ isLongPressSpeedUp, isCurrent }">
    <view v-if="isLongPressSpeedUp && isCurrent" class="speed-tip">
      <text>长按快进中</text>
    </view>
  </template>
</l-video-swiper>

进度条模式

通过 progressMode 控制进度条显示方式:

  • 'native':使用原生 video 的进度条
  • 'custom':插件自定义进度条(抖音风格,支持拖拽、暂停放大、拖拽时显示时间)
  • 'none':不显示任何进度条
<!-- 使用自定义进度条 -->
<l-video-swiper :videoList="videoList" progressMode="custom" />

<!-- 不显示进度条 -->
<l-video-swiper :videoList="videoList" progressMode="none" />

自定义进度条支持拖拽跳转,有三种视觉状态:

  • 播放中:细线(3px),白色进度
  • 暂停:中等粗细(4px)+ 圆形拖拽手柄
  • 拖拽中:粗线(6px)+ 大手柄 + 时间显示 + 主题色

拖拽时触发 progressDragStartprogressDragMoveprogressDragEnd 事件。

进度条样式自定义

通过 CSS 变量覆盖进度条样式:

.l-video-swiper {
  --l-video-swiper-progress-bar-active-color: #1890ff;
  --l-video-swiper-progress-handle-active-color: #1890ff;
  --l-video-swiper-progress-playing-height: 2px;
}

也可通过 lClassProgress* 属性设置自定义类名(仅 uni-app x):

<l-video-swiper
  :videoList="videoList"
  progressMode="custom"
  lClassProgress="my-progress"
  lClassProgressTrack="my-progress-track"
  lClassProgressBar="my-progress-bar"
  lClassProgressHandle="my-progress-handle"
/>

缓存播放进度

设置 cacheProgress=true 后,切换视频时缓存当前播放进度,再次切回从上次位置继续。

<l-video-swiper :videoList="videoList" :cacheProgress="true" />

自定义字段映射

如果数据字段名不是默认的 src / poster,可通过 *Key 属性配置。

<l-video-swiper
  :videoList="videoList"
  srcKey="video_url"
  posterKey="cover_url"
  objectFitKey="fit"
  titleKey="name"
/>
const videoList = [
  { video_url: 'https://...', cover_url: 'https://...', fit: 'cover', name: '标题' }
];

循环滑动

circular=true 时首尾衔接循环,适合 Feed 流;circular=false 时边界回弹,适合剧集列表。

<!-- Feed 流:首尾循环 -->
<l-video-swiper :videoList="videoList" :circular="true" />

<!-- 剧集列表:有明确起止 -->
<l-video-swiper :videoList="videoList" :circular="false" />

API 文档

l-video-swiper Props 分类

基础配置(最常用)

参数 说明 类型 默认值 可选值
videoList 视频数据列表 UTSJSONObject[] [] -
srcKey 视频地址字段名 string 'src' -
posterKey 封面图字段名 string 'poster' -
objectFitKey object-fit 字段名 string 'objectFit' contain / cover
titleKey 标题字段名 string 'title' -
bufferCount 缓冲区数量(建议奇数:3/5/7) number 3 -
autoplay 自动播放当前视频 boolean true -
autoReplay 视频播放结束后自动重播 boolean false -
circular 滑动首尾衔接循环 boolean false -
autoChange 播放结束自动切换下一个 boolean false -
autoObjectFit 根据宽高比自动设置 object-fit boolean true -
controls 显示原生控制栏 boolean false -
showCenterPlayBtn 显示中间播放按钮 boolean true -
progressMode 进度条模式 string 'native' native / custom / none
muted 静音播放 boolean false -
disableSwipe 禁止滑动切换 boolean false -
clickToggle 点击切换播放状态,false 时只派发 click 事件不切换播放 boolean true -
cacheProgress 缓存播放进度,切回从上次位置继续 boolean false -

播放控制

参数 说明 类型 默认值 可选值
playbackRate 初始播放速率 number 1.0 0.5 / 0.75 / 1.0 / 1.25 / 1.5 / 2.0 等
longPressSpeed 长按加速倍率 number 2.0 -
loadMoreOffsetCount 距末尾多少条触发 load number 2 -
maxErrorCount 单视频最大错误重试次数 number 3 -

滑动手势

参数 说明 类型 默认值 可选值
duration 切换动画时长(ms) number 300 -
touchRatio 触摸位移比例 number 1 -
resistanceRatio 边界阻尼系数(0~1) number 0.85 -
threshold 触发滑动的最小位移(px) number 5 -
switchThreshold 触发切换的距离比例 number 0.3 -
velocityThreshold 触发切换的速度阈值(px/ms) number 0.5 -
longSwipes 允许长按慢速滑动触发切换 boolean true -
longSwipesMs 判定为长按的最小时长(ms) number 300 -
longSwipesRatio 长按模式滑动距离比例阈值 number 0.3 -
shortSwipes 允许短滑动触发切换 boolean true -
preventClicks 滑动时阻止点击事件 boolean true -
swipeDelay 滑动延迟(ms),0 表示不延迟 number 0 -
swipeAwaitAnimation 等待切换动画完成后再响应下一次滑动 boolean true -

样式自定义

参数 说明 类型 默认值 可选值
lClass 根元素自定义类名 string | object null -
lStyle 根元素自定义样式 string | object null -
lClassProgress 进度条容器自定义类名 string | object null -
lClassProgressTrack 进度条轨道自定义类名 string | object null -
lClassProgressBar 进度条已播放部分自定义类名 string | object null -
lClassProgressHandle 进度条拖拽手柄自定义类名 string | object null -

注意lClass* 属性为 externalClasses,仅 uni-app x (UTS) 平台支持。其他平台请使用 CSS 变量或父级样式覆盖。

l-video-swiper Events

事件名 参数 说明
change VideoSwiperChangeDetail 视频切换
load - 需要加载更多视频
refresh - 下拉刷新(在第一个视频继续下拉触发)
play UniEvent 视频开始播放
pause UniEvent 视频暂停
ended - 视频播放结束
timeupdate UniVideoTimeUpdateEvent 播放进度更新
waiting UniEvent 视频缓冲中
error UniVideoErrorEvent 视频播放错误
loadedmetadata UniVideoLoadedMetadataEvent 元数据加载完成
controlstoggle UniVideoControlsToggleEvent 控制栏显隐
click - 点击视频(clickToggle=true 时延迟300ms切换播放状态,双击时不切换)
doubleClick { clickCount } 连续点击视频(clickCount >= 2,阻止单击切换播放)
progressDragStart { percent, currentTime, duration } 进度条开始拖拽
progressDragMove { percent, currentTime, duration } 进度条拖拽移动
progressDragEnd { percent, currentTime, duration } 进度条拖拽结束
mutechange boolean 静音状态变化

change 事件参数

type VideoSwiperChangeDetail = {
  index: number;            // 当前视频在 videoList 中的索引
  detail: UTSJSONObject;    // 当前视频的原始数据
  direction: 'up' | 'down' | ''; // 切换方向:up=下一个,down=上一个,''=初始化
};

l-video-swiper Methods(通过 ref 暴露)

<l-video-swiper ref="swiperRef" :videoList="videoList" />
const swiperRef = ref<LVideoSwiperComponentPublicInstance|null>(null);

// 跳转到指定索引
swiperRef.value!.jumpToVideo(5);  // 等同于 initSwiperData(5)

// 播放 / 暂停切换
swiperRef.value!.togglePlay();

// 静音切换(触发 mutechange 事件)
swiperRef.value!.toggleMuted();

// 跳转到指定时间点(秒)
swiperRef.value!.playSeeked(30);

// 暂停
swiperRef.value!.pause();

// 恢复播放
swiperRef.value!.resume();

// 设置播放倍速
swiperRef.value!.setPlaybackRate(1.5);

// 获取当前视频索引
const idx = swiperRef.value!.getCurrentIndex();

// 获取当前静音状态
const isMuted = swiperRef.value!.getMuted();

// 长按加速(手动触发)
swiperRef.value!.startLongPressSpeedUp();
swiperRef.value!.endLongPressSpeedUp();

l-video-swiper Slots

插槽名 说明 上下文数据 使用场景
default 自定义视频浮层 见下方表格 点赞、评论、分享等 UI

default 插槽上下文数据

字段 类型 说明
item UTSJSONObject 当前视频的原始数据
index number 当前视频在 videoList 中的索引
isCurrent boolean 是否为当前正在播放的视频(可用于控制浮层显隐)
playing boolean 当前视频是否正在播放
isLongPressSpeedUp boolean 是否正在长按加速播放
currentTime number 当前播放时间(秒)
duration number 总时长(秒)
progressPercent number 播放进度百分比(0~100)
formatTime string 格式化的当前播放时间(mm:ss,超过1小时为 HH:MM:SS)

主题定制

组件提供了以下 CSS 变量,可用于自定义进度条样式:

变量名称 默认值 描述
--l-video-swiper-progress-track-bg rgba(255,255,255,0.2) 进度条轨道背景色
--l-video-swiper-progress-bar-color rgba(255,255,255,0.7) 已播放进度颜色
--l-video-swiper-progress-bar-active-color #fe2c55 拖拽时进度颜色
--l-video-swiper-progress-handle-color #fff 拖拽手柄颜色
--l-video-swiper-progress-handle-active-color #fe2c55 拖拽时手柄颜色
--l-video-swiper-progress-time-color rgba(255,255,255,0.9) 时间文字颜色
--l-video-swiper-progress-time-font-size 12px 时间文字大小
--l-video-swiper-progress-playing-height 3px 播放中进度条高度
--l-video-swiper-progress-paused-height 4px 暂停时进度条高度
--l-video-swiper-progress-dragging-height 28px 拖拽时进度条区域高度
--l-video-swiper-progress-track-dragging-height 6px 拖拽时轨道高度
--l-video-swiper-progress-handle-paused-size 12px 暂停时手柄大小
--l-video-swiper-progress-handle-dragging-size 16px 拖拽时手柄大小

使用示例

方式一:通过父级或根节点设置主题变量(推荐)

<view class="swiper-wrapper">
    <l-video-swiper :videoList="videoList" progressMode="custom" />
</view>

<style>
.swiper-wrapper {
    --l-video-swiper-progress-bar-active-color: #1890ff;
    --l-video-swiper-progress-handle-active-color: #1890ff;
}
</style>

方式二:通过 lStyle 属性直接设置

<l-video-swiper
    :videoList="videoList"
    progressMode="custom"
    :lStyle="{
        '--l-video-swiper-progress-bar-active-color': '#1890ff'
    }"
/>

方式三:通过 lClass 配合 CSS 样式

<l-video-swiper :videoList="videoList" progressMode="custom" lClass="custom-swiper" />

<style>
.custom-swiper {
    --l-video-swiper-progress-bar-active-color: #1890ff;
}
</style>

⚠️ 重要提示

<!-- 错误写法:不要在自定义组件上直接使用 class -->
<l-video-swiper class="custom-style" />

<!-- 正确写法:使用 lClass 或 lStyle -->
<l-video-swiper lClass="custom-style" />
<l-video-swiper :lStyle="{ '--l-video-swiper-progress-bar-color': '#1890ff' }" />

<!-- 正确写法:在父级上设置 class -->
<view class="custom-style">
  <l-video-swiper :videoList="videoList" progressMode="custom" />
</view>

快速预览

导入插件后,可以直接使用以下标签查看演示效果:

<!-- 代码位于 uni_modules/lime-video-swiper/components/lime-video-swiper -->
<lime-video-swiper />

插件标签说明

标签类型 示例 说明
组件标签 l-video-swiper 视频滑动核心组件
演示标签 lime-video-swiper 演示组件,包含抖音风格 UI 示例

常见问题

1. 如何实现抖音/TikTok 的 UI 效果?

本组件只负责视频滑动切换,不包含任何 UI。你需要通过 default 插槽自行实现:

  • 右侧操作栏:头像、点赞、评论、收藏、分享等按钮
  • 底部信息:作者昵称、视频描述、音乐信息
  • 评论区:从底部弹出的评论面板,打开时设置 disableSwipe=true 禁止滑动
  • 浮层显隐:使用 isCurrent 判断当前项,配合 opacity 过渡控制浮层显隐
  • 长按快进:使用 isLongPressSpeedUp 显示加速提示
  • 连续点击点赞:监听 doubleClick 事件,clickCount 可获取连续点击次数,显示爱心动画

2. circular 设为 true 还是 false?

  • true:上下滑动可首尾衔接循环,类似抖音/TikTok 的体验,适合 Feed 流。
  • false:到首尾时边界透明(不会显示相邻内容),更适合剧集列表等有明确起止的场景。

3. 数据追加不重置

组件监听 videoList 变化时,会智能判断:

  • 首次设置 → 全量初始化
  • 后续追加 → 增量扩展 nextQueue,不重建当前播放位置
  • 索引越界 → 自动调整到末尾

直接 videoList.value.push(item) 即可,无需手动调用 initSwiperData

4. 播放倍速切换后不生效?

通过 setPlaybackRate 设置的倍速会在视频切换后自动保持,无需重复设置。如果倍速未生效,请确认是否通过 ref 调用了 setPlaybackRate 方法,而非仅修改 props。

5. 视频错误自动跳过

每个视频独立维护错误计数,同一视频连续失败 maxErrorCount 次后,组件会自动切换到下一个视频。切换到其他视频再切回不会重置错误计数。非播放 slot 的错误事件会被忽略,避免空内容触发误判。

6. disableSwipe 与 clickToggle

  • disableSwipe 只禁止滑动切换,不影响点击播放/暂停
  • clickToggle 控制点击是否切换播放状态(默认 true)
  • 评论区场景建议同时设置 disableSwipe=true + clickToggle=false,监听 click 事件关闭评论区

7. 缓存播放进度

设置 cacheProgress=true 后,切换视频时会缓存当前播放进度,再次切回该视频时从上次位置继续播放。视频播放结束后自动清除缓存。切换时先 seek 到缓存位置再播放,避免从头播放闪烁。

8. 进度条三种模式

  • native(默认):使用原生 video 的进度条(通过 show-progress 属性控制)。APP-VUE 使用 renderjs 时自动降级为 custom
  • custom:插件自定义进度条,支持拖拽跳转、暂停时放大手柄、拖拽时显示时间。可通过 CSS 变量或 lClassProgress* 属性自定义样式。
  • none:不显示任何进度条,适合需要完全自定义进度条的场景。

9. 下拉刷新

在第一个视频继续下拉超过视口高度 25% 时触发 refresh 事件。收到事件后,替换 videoList 即可自动重新初始化:

const onRefresh = () => {
  const newList = fetchNewData();
  videoList.value = newList;
};

10. autoChange 循环模式

autoChange=truecircular=true 时,播放到最后一条视频会自动循环回第一条继续播放。

11. 长按加速播放

设置 longPressSpeed 可配置长按加速倍率(默认 2.0)。长按视频时自动加速播放,松开后恢复原速。在 slot 中通过 isLongPressSpeedUp 判断当前是否处于加速状态,可用于显示加速提示 UI。

12. bufferCount 配置

bufferCount 控制同时渲染的视频节点数量,默认为 3。增大该值(如 5 或 7)可预加载更多相邻视频,减少滑动时的加载等待,但会增加内存占用。建议使用奇数。

隐私、权限声明

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

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

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

暂无用户评论。