前段时间有给大家分享一个vue3网页聊天实例,今天分享的是最新开发vue3.0小视频实例。
vue3.x-douyin短视频 基于
vue3.x+vuex4+vue-router+vant3.x+v3popup
等技术搭建的一款仿制抖音小视频/微信直播界面实战项目。
vue3DouYin支持滑屏切换视频、点赞/评论/弹幕/送礼物等功能。
实现技术
- 编辑器:Vscode
- MVVM框架:Vue^3.0.5
- 状态管理:Vuex^4.0.0-rc.2
- 页面路由:Vue-Router^4.0.3
- UI组件库:Vant^3.0.4 (有赞手机端vue3组件库)
- 弹框组件:v3popup(基于vue3自定义手机端弹出层组件)
- 字体图标:阿里iconfont图标
- 顶部条+底部栏:基于vue3自定义navbar/tabbar组件
项目结构
预览图
vue3.0自定义移动端弹框
项目中使用到的弹框组件,是vue3自定义组件实现功能的。
之前有过一篇分享文章,感兴趣的可以去看看哈。
vue3系列:vue3.0自定义弹框组件V3Popup|vue3.x手机端弹框组件
vite项目配置
使用vite搭建的项目,会有一个vite.config.js配置文件
/**
* Vite2项目配置
*/
import vue from '@vitejs/plugin-vue'
import path from 'path'
/**
* @type {import('vite').UserConfig}
*/
export default {
plugins: [vue()],
build: {
// 基本目录
// base: '/',
/**
* 输出文件目录
* @default dist(默认)
*/
// outDir: 'target',
},
// 环境配置
server: {
// 自定义接口
port: 3000,
// 是否自动浏览器打开
open: false,
// 是否开启https
https: false,
// 服务端渲染
ssr: false,
// 代理配置
proxy: {
// ...
}
},
// 设置路径别名
alias: {
'@': path.resolve(__dirname, './src'),
'@components': path.resolve(__dirname, './src/components'),
'@views': path.resolve(__dirname, './src/views')
}
}
vue3.0导入公共组件
/**
* 引入公共组件
*/
// 引入Vant3.x组件库
import Vant from 'vant'
import 'vant/lib/index.css'
// 引入Vue3.x移动端弹层组件
import V3Popup from '@components/v3popup'
import NavBar from '@components/navBar.vue'
import TabBar from '@components/tabBar.vue'
import Utils from './utils'
import Storage from './storage'
const Plugins = (app) => {
app.use(Vant)
app.use(V3Popup)
// 注册公用组件
app.component('navbar', NavBar)
app.component('tabbar', TabBar)
app.provide('utils', Utils)
app.provide('storage', Storage)
}
vue3.0实现小视频/直播功能
如下图:小视频页面整体分为顶部导航条、视频信息区、底部Tab栏三个部分。
<!-- //聊天模板 -->
<template>
<div class="bg-282a3a">
<!-- >>顶部 -->
<navbar bgcolor="linear-gradient(to right, #36384a, #36384a)" center fixed zIndex="1011">
<template #backIco><i class="iconfont icon-back"></i></template>
<template #title><em class="ff-gg">Vue3.0交流</em></template>
</navbar>
<!-- >>主页面 -->
<div class="vui__scrollview scrolling flex1" ref="scrollview" @click="handleMsgPanelClicked">
<!-- ...渲染消息记录 -->
<div class="vChatMsg-cnt">
...
</div>
</div>
<!-- >>底部功能面板区 -->
<div class="vui__footTool">
<!-- //输入框模块 -->
<div class="vui__editorPanel flexbox">
<div class="vui__editor flex1">
<editor ref="editorRef" v-model="editorText" @clickFn="handleEditorClick" @focusFn="handleEditorFocus" @blurFn="handleEditorBlur" />
</div>
<div class="vui__editor-btn" @click="handleEmojChooseView(0)"><i class="iconfont icon-face"></i></div>
<div class="vui__editor-btn" @click="handleEmojChooseView(1)"><i class="iconfont icon-tianjia"></i></div>
<div class="vui__editor-btn btn-submit" @click="handleSubmit"><i class="iconfont icon-up"></i></div>
</div>
<!-- //表情、选择模块 -->
<div v-show="isShowFootBar" class="vui__choosePanel">
<!-- 表情 -->
<div v-show="showFootBarIndex==0" class="vui__emotion">
<div class="vui__emotion-wrap flexbox flex-col">
<div class="vui__emotion-tabs flexbox flex-alignc">
<!-- <span class="item"><i class="iconfont icon-tianjia fs-36"></i></span> -->
<div class="flex1 flexbox">
<span v-for="(item,index) in emojList" :key="index" class="item" :class="{'on': item.selected}" @click="handleEmojTab(index)"><img :src="item.pathLabel" /></span>
</div>
<span class="item del" @click="handleDelClicked"><i class="iconfont icon-del2 fs-50"></i></span>
</div>
<div v-for="(item,index) in emojList" :key="index" class="vui__emotion-cells flex1" :class="{'cur': item.selected}">
<div :class="item.type == 'emoj' ? 'face__sm_list' : 'face__lg_list'">
<div class="face_list">
<div v-for="(item2,index2) in item.nodes" :key="index2" class="item">
<img v-if="item.type=='emoj'" :src="item2" class="emoj" @click="handleEmojClicked" />
<img v-else :src="item2" @click="handleGifClicked(item2)" />
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 选择区域 -->
<div v-show="showFootBarIndex==1" class="vui__choose vui__hairline-top">
<div class="vui__choose-cells">
<ul class="clearfix">
<li><div class="item"><span class="ico"><i class="iconfont icon-tupian"></i><input ref="pickImageRef" type="file" accept="image/*" @change="handleChooseImage" /></span><em>照片</em></div></li>
<li><div class="item"><span class="ico"><i class="iconfont icon-xiangji1"></i><input ref="pickVideoRef" type="file" accept="video/*" @change="handleChooseVideo" /></span><em>视频</em></div></li>
<li><div class="item" @click="isShowSendRedPacket=true"><span class="ico"><i class="iconfont icon-hongbao"></i></span><em>红包</em></div></li>
<li><div class="item" @click="handleShakeWin"><span class="ico"><i class="iconfont icon-qiehuan"></i></span><em>抖一抖</em></div></li>
<li><div class="item"><span class="ico"><i class="iconfont icon-fujin"></i></span><em>位置</em></div></li>
<li><div class="item"><span class="ico"><i class="iconfont icon-shoucang"></i></span><em>我的收藏</em></div></li>
<li><div class="item"><span class="ico"><i class="iconfont icon-mingpian2"></i></span><em>名片</em></div></li>
</ul>
</div>
</div>
</div>
</div>
<!-- ……网址预览模板 -->
<div v-if="isShowLinkView" class="nt__statePopup nt__lkView-wrap">
<navbar bgcolor="linear-gradient(to right, #36384a, #36384a)" center zIndex="2021">
<template #backIco><i class="iconfont icon-arrL"></i></template>
<template #title><div class="flexbox flex-alignc flex-justifyc">链接预览</div></template>
<template v-slot:right>
<div class="ml-30"><i class="iconfont icon-copylink"></i></div>
<div class="ml-30"><i class="iconfont icon-fenxiang"></i></div>
</template>
</navbar>
<div class="nt__statePopup-wrap">
<!-- //网址iframe -->
<iframe class="lkView" scrolling="auto" allowtransparency="true" frameBorder="0" :src="linkView"></iframe>
</div>
</div>
<!-- ……视频播放器模板 -->
<div v-if="isShowVideoPlayer" class="nt__statePopup nt__vplayer-wrap">
<navbar bgcolor="linear-gradient(to right, #36384a, #36384a)" center zIndex="2021">
<template #backIco><i class="iconfont icon-arrL"></i></template>
<template v-slot:right>
<div class="ml-30"><i class="iconfont icon-fenxiang1"></i></div>
<div class="ml-30"><i class="iconfont icon-vdots"></i></div>
</template>
</navbar>
<div class="nt__statePopup-wrap">
<!-- //视频video -->
<video class="vplayer" ref="playerRef" :src="videoList.videosrc" :poster="videoList.imgsrc" autoplay preload="auto" controls
x5-video-player-fullscreen="true"
webkit-playsinline="true"
x-webkit-airplay="true"
playsinline="true"
x5-playsinline
/>
</div>
</div>
<!-- ……红包弹窗模板(開) -->
<v3-popup v-model="isShowRedPacket" xclose xcolor="#ffe7bb" shadeClose="false">
...
</v3-popup>
<!-- ……发红包弹窗模板 -->
<v3-popup v-model="isShowSendRedPacket" xclose xposition="top" xcolor="#ffe7bb">
<redPacket />
</v3-popup>
<!-- ……群设置模板 -->
<v3-popup v-model="isShowSettingPopup" position="right" popupStyle="background:#36384a;">
<pageSetting />
</v3-popup>
</div>
</template>
底部人性化的迷你进度条,实时看到视频播放进度。
ok,基于vue3+vant3.x实战短视频/直播实例就分享到这里。