vue3.0版模仿抖音短视频|微信直播实例

#1

前段时间有给大家分享一个vue3网页聊天实例,今天分享的是最新开发vue3.0小视频实例。

vue3.x-douyin短视频 基于vue3.x+vuex4+vue-router+vant3.x+v3popup等技术搭建的一款仿制抖音小视频/微信直播界面实战项目。

%E6%9C%AA%E6%A0%87%E9%A2%98-pp4

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组件

项目结构

360%E6%88%AA%E5%9B%BE20210202094413416

预览图

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实战短视频/直播实例就分享到这里。:muscle:

基于vue3.x+vant-ui模仿微信APP聊天界面|vue3聊天实例

qrcode_%E5%85%AC%E4%BC%97%E5%8F%B7_%E7%89%A9%E6%96%992