uni-app+vue3+pinia2+uv-ui实战:仿抖音app小视频+直播+聊天系统
本项目基于uni-app与Vue3技术栈,结合Pinia2状态管理和uv-ui组件库,从零开始搭建了一个仿抖音的跨端应用。该应用集成了短视频浏览、实时聊天与直播带货功能,支持全屏沉浸式体验,并能够编译运行到H5、小程序及App端。
技术栈概览
- 开发工具:HbuilderX 4.66
- 核心框架:Uniapp + Vue3 + Vite5 + Nvue
- 状态管理:Pinia2,配合pinia-plugin-unistorage进行本地缓存持久化
- UI组件:uv-ui与vk-uview组件库
- 自定义组件:封装了uaNavbar导航栏与uaTabbar底部栏组件
- 弹框组件:使用uaPopup实现多端统一的弹框
- 多端支持:可编译至H5、各平台小程序及App端
项目框架结构
项目采用uni-app结合Vue3的Composition API与setup语法进行开发,确保了代码的模块化与可维护性。整体架构清晰,便于功能扩展与多端适配。
短视频模块实现
短视频模块模仿了抖音的全屏沉浸式上下滑动切换效果。界面主要分为顶部固定标签栏、视频播放区以及底部视频信息浮层三大部分。
核心实现利用了uni-app的swiper组件进行垂直滑动管理,每个swiper-item内嵌video组件用于播放。视频播放器支持弹幕、循环播放与自动播放,并实现了自定义的迷你进度条拖拽控制。
以下为部分关键代码示例:
<ua-layout>
<view class="ua__swipervideo flex1">
<swiper
class="ua__swipervideo-wrap flex1"
:current="currentVideo"
vertical
:circular="true"
:duration="200"
@change="handleChange"
@transition="handleTransition"
>
<swiper-item v-for="(item, index) in videoList" :key="index">
<video
class="ua__swipervideo-player flex1"
:id="'uplayer' + index"
:src="item.src"
:danmu-list="item.danmu"
:enable-danmu="true"
:controls="false"
:loop="true"
:autoplay="index == currentVideo"
:show-center-play-btn="false"
object-fit="contain"
@click="handleClickVideo"
@play="isPlaying=true"
@timeupdate="handleTimeUpdate"
>
</video>
<!-- 浮层信息展示区,包含作者、描述、点赞、评论等交互操作 -->
<view class="ulive__video-float__info flexbox flex-col">
<!-- 信息展示布局 -->
</view>
</swiper-item>
</swiper>
<!-- 顶部固定标签栏 -->
<view class="ulive__video-header__tabs">
<uv-tabs :current="tabsCurrent" :list="tabsList" />
</view>
<!-- 播放控制与进度条 -->
<view v-if="!isPlaying" class="ua__swipervideo-playbtn" @click="handleClickVideo">
<text class="ua__swipervideo-playico welive-icon welive-icon-play nvueicon"></text>
</view>
<view v-if="sliderValue > 0" class="ua__swipervideo-slider">
<slider
:value="sliderValue"
:step="sliderStep"
:max="sliderMaxValue"
activeColor="#fff"
backgroundColor="rgba(255,255,255,.2)"
@changing="onSliderChanging"
@change="onSliderChange"
/>
</view>
</view>
</ua-layout>
进度条交互通过监听视频的timeupdate事件,并绑定slider组件的changing和change事件来实现:
// 监听播放进度
const handleTimeUpdate = (e) => {
let { currentTime, duration } = e.detail
sliderValue.value = currentTime
sliderMaxValue.value = duration
sliderStep.value = currentTime / duration
}
// 滑动条拖动处理
const onSliderChanging = (e) => {
sliderValue.value = e.detail.value
handlePause()
}
const onSliderChange = (e) => {
sliderValue.value = e.detail.value
let video = getVideoContext()
if(!video) return
video.seek(sliderValue.value)
handlePlay()
}
聊天模块
聊天功能模块迁移自之前已实现的uni-app仿微信聊天项目。它提供了完整的实时消息交互界面,支持文本、语音等多种消息类型,并集成了朋友圈动态等社交功能。
直播模块详解
直播模块模拟了电商直播场景,界面分为顶部主播信息区、直播视频流、滚动消息区(展示用户加入、送礼、商品讲解)以及底部互动工具栏。
实现上,同样使用swiper管理多个直播流,并在浮层中通过嵌套swiper实现“清屏”与“互动层”的切换。互动层包含:
- 顶部区域:展示主播头像、关注状态、直播间标签(如小时榜)以及红包、福袋等互动入口。
- 底部区域:
- 商品提示栏:显示正在讲解的热卖商品。
- 动态消息区:使用scroll-view展示用户加入、送礼等滚动消息。
- 商品讲解浮层:以卡片形式突出显示当前讲解的商品详情。
- 工具栏:提供输入框、购物车、礼物菜单等互动入口。
核心结构代码如下:
<ua-layout>
<view class="ua__swipervideo flex1">
<swiper class="ua__swipervideo-wrap flex1" :current="currentLive" vertical @change="handleChange">
<swiper-item v-for="(item, index) in liveList" :key="index">
<video
class="ua__swipervideo-player flex1"
:id="'uplayer' + index"
:src="item.src"
:controls="false"
:loop="true"
:autoplay="index == currentLive"
object-fit="contain"
>
</video>
<!-- 直播互动浮层 -->
<swiper class="ulive__swiperscreen flex1" :current="1">
<swiper-item>清屏视图</swiper-item>
<swiper-item>
<view class="ulive__headlayer"><!-- 顶部信息区 --></view>
<view class="ulive__footlayer">
<!-- 商品提示 -->
<view class="ulive__ft-livewrap-placeholder">
<view class="ulive__ft-livewrap-hotbuy flexbox flex-row">
<image class="gimg" :src="item.poster" mode="aspectFill" />
<view class="ginfo flex1">
<view class="flexbox flex-row"><text class="user c-ffdd1a">Andy</text><text class="c-fff">等{{item.saleNum}}人在购买</text></view>
<text class="gdesc clamp1">{{item.desc}}</text>
</view>
<view class="btn"><text class="btntext">去购买</text></view>
</view>
</view>
<!-- 动态消息(加入、送礼) -->
<view class="ulive__ft-livewrap-animateview flexbox flex-col">
<!-- 加入直播间提示 -->
<!-- 送礼提示 -->
</view>
<!-- 聊天与商品讲解区 -->
<view class="ulive__ft-livewrap-mixinview flexbox flex-row">
<view class="ulive__ft-livewrap-chats flex1">
<scroll-view class="ulive__ft-livewrap-chats__scrollview flex1" scroll-y>
<!-- 消息列表,区分通知、礼物和普通聊天 -->
<block v-for="(msgitem, msgidx) in item.message" :key="msgidx">
<view v-if="msgitem.type == 'notice'" class="notice"><text class="noticetext">{{msgitem.content}}</text></view>
<view v-else-if="msgitem.type == 'gift'" class="gift">
<text class="giftuser">{{msgitem.user}}</text>
<text class="gifttext">送出了{{msgitem.content}}</text>
</view>
<view v-else class="msg">
<text v-if="msgitem.tag" class="tag">{{msgitem.tag}}</text>
<text class="user">{{msgitem.user}}</text>
<text class="text">{{msgitem.isbuy ? '正在购买' : msgitem.content}}</text>
</view>
</block>
</scroll-view>
</view>
<!-- 商品讲解侧边栏 -->
<view v-if="isVisibleGoodsTalk" class="ulive__ft-livewrap-activegoods">
<view class="ulive__ft-livewrap-activegoods__card">
<view class="gwrap" @click="toGoodsDetail">
<image class="gimg" :src="item.poster" mode="aspectFill" />
<view class="waves"><text class="c-fff fs-24">讲解中</text></view>
</view>
<view class="ginfo flexbox flex-col">
<text class="clamp1 fs-24">{{item.desc}}</text>
<text class="clamp1 fs-24 c-eb4868">7天无理由退货</text>
</view>
<view class="btn flexbox flex-row">
<text class="flex1 c-fff fs-28">¥79.00</text>
<text class="qiang">抢</text>
</view>
</view>
</view>
</view>
<!-- 底部工具栏 -->
<view class="ulive__ft-livewrap-toolbar flexbox flex-row">
<view class="editorwrap flex1" @click="handleOpenChatbox"><text class="editorwrap-text">说点什么...</text></view>
<view class="btnwrap flexbox flex-row">
<view class="btn" @click="handleOpenMenus"><uv-icon name="grid" color="#3c9cff" size="22" /></view>
<view class="btn" @click="handleOpenGoods(item)"><uv-icon name="shopping-cart-fill" color="#ffaa00" size="24" /></view>
<view class="btn" @click="handleOpenGifts"><uv-icon name="gift" color="#ff0ad3" size="22" /></view>
</view>
</view>
</view>
</swiper-item>
</swiper>
</swiper-item>
</swiper>
</view>
</ua-layout>
总结
本项目展示了利用uni-app和Vue3生态系统构建功能复杂的跨端移动应用的可行性。通过封装自定义组件(如导航栏、底部栏)、集成状态管理以及优化多端兼容性,成功实现了仿抖音的核心交互体验,包括丝滑的短视频切换、实时聊天互动与完整的直播带货流程。该实践为开发者提供了一个可参考的跨端开发范例。