vue.js项目实战运用篇之抖音视频APP-第五节:视频播放列表组件功能

Posted enjsky.G

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vue.js项目实战运用篇之抖音视频APP-第五节:视频播放列表组件功能相关的知识,希望对你有一定的参考价值。

【温馨提示】:若想了解更多关于本次项目实战内容,可转至vue.js项目实战运用篇之抖音视频APP-项目规划中进一步了解项目规划。

【项目地址】
项目采用Git进行管理,最终项目将会发布到GitHub中,感兴趣的小伙伴们可以一起学习,共同完善本项目。
项目地址:GitHub


第五节:视频播放列表组件功能

vue-awesome-swiper介绍

众所周知的图片轮播插件swiper,快速,简单,高效,稳定。不过最新的swiper6对vue的兼容却不如人意。那么我们怎么解决这一问题呢?可使用第三轮播插件,运用javascript编写的兼容vue轮播插件。
详细内容:vue-awesome-swiper
项目地址:vue-awesome-swiper

vue-video-player介绍

vue中的视频播放插件。
项目地址:vue-video-player

在项目中安装配置插件

1.安装vue-awesome-swiper
【命令】:

npm install swiper vue-awesome-swiper

2.vue-video-player安装
【命令】:

npm install vue-video-player 

3.引入并注册插件
在main.js文件中引入安装好的插件文件,代码如下:

// 滑动特效插件
import VueSwiper from 'vue-awesome-swiper';
//import 'swiper/css/swiper.css';
import 'swiper/swiper-bundle.css';
// 视频播放插件
import VueVideoPlayer from 'vue-video-player';
import 'video.js/dist/video-js.css';
//注册
Vue.use(VueSwiper);
Vue.use(VueVideoPlayer);

【温馨提示】
1.引入以上插件文件需在App.vue前引入,可能会报错。
2.旧版本的Swiper样式为:import ‘swiper/css/swiper.css’;若引入旧版本的swiper可能会报错,将其替换为import ‘swiper/swiper-bundle.css’;即可。

4.配置路由
视频列表是在首页的关注和推荐两个页面中的内容,所以我们需要在这两个页面添加视频列表子路由。
路径:src/router/index.js。
配置代码如下:

import Vue from 'vue';
import VueRouter from 'vue-router';
import Home from '../views/Home.vue';

Vue.use(VueRouter);

const routes = [
  {
    path: '/',
    redirect: '/index/recommend/', // app打开之后 默认跳转到首页的推荐标签栏
  },
  {
    path: '/index',
    redirect: '/index/recommend/', // app打开之后 默认跳转到首页的推荐标签栏
  },
  {
    path: '/',
    name: 'Home',
    component: Home,
    children: [
      {
        path: '/index', // 首页页面路由
        name: 'index',
        component: () => import(/* webpackChunkName: "Index" */ '../views/index/Index.vue'),
        children: [
          {
            path: 'follows', // 关注页面路由
            name: 'follows',
            component: () => import(/* webpackChunkName: "Follows" */ '../views/follow/Follows.vue'),
            children: [
              {
                path: 'reVidelList', // 视频页面路由
                name: 'reVidelList',
                component: () => import(/* webpackChunkName: "reVidelList" */ '../common/components/index/VideoList.vue'),
              },
            ],
          },
          {
            path: 'recommend', // 推荐页面路由
            name: 'recommend',
            component: () => import(/* webpackChunkName: "Recommend" */ '../views/recommend/Recommend.vue'),
            children: [
              {
                path: 'reVidelList', // 视频页面路由
                name: 'reVidelList',
                component: () => import(/* webpackChunkName: "reVidelList" */ '../common/components/index/VideoList.vue'),
              },
            ],
          },
        ],
      },
      {
        path: '/friends', // 朋友页面路由
        name: 'friends',
        component: () => import(/* webpackChunkName: "fllow" */ '../views/friends/Friends.vue'),
      },
      {
        path: '/news', // 消息页面路由
        name: 'news',
        component: () => import(/* webpackChunkName: "news" */ '../views/news/News.vue'),
      },
      {
        path: '/me', // 我的信息页面路由
        name: 'me',
        component: () => import(/* webpackChunkName: "me" */ '../views/me/Me.vue'),
      },
    ],
  },
  {
    path: '/issue', // 发布页面路由
    name: 'issue',
    component: () => import(/* webpackChunkName: "issue" */ '../views/issue/Issue.vue'),
  },
];

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes,
});

export default router;

【温馨提示】
在关注和推荐页面下增加了如下子路由代码:
children: [
{
path: ‘reVidelList’, // 视频页面路由
name: ‘reVidelList’,
component: () => import(/* webpackChunkName: “reVidelList” */ ‘…/common/components/index/VideoList.vue’),
},
],

视频组件结构分析及实现

1.组件结构
在这里插入图片描述
2.Videos视频播放组件实现
通过css的transform属性 改变播放按钮的位置;
通过 /deep/ 实现样式穿透。
代码如下:

<template>
  <div class="videos">
    <video-player class="video-player vjs-custom-skin"
                  ref="videoPlayer"
                  :playsinline="true"
                  :options="playerOptions"
    ></video-player>
  </div>
</template>

<script>
import { videoPlayer } from 'vue-video-player';

export default {
  name: 'Videos',
  props: ['video', 'index'],
  data() {
    return {
      playerOptions: {
        autoplay: false, // 如果true,浏览器准备好时开始回放。
        muted: true, // 默认情况下将会消除任何音频。
        loop: true, // 导致视频一结束就重新开始。
        preload: 'auto',
        fluid: true, // 当true时,Video.js player将拥有流体大小。换句话说,它将按比例缩放以适应其容器。
        sources: [
          {
            src: this.video.url,
            type: 'video/mp4', // 类型
          },
        ],
        // poster: "../../static/images/test.jpg", //你的封面地址
        width: document.documentElement.clientWidth,
        notSupportedMessage: '此视频暂无法播放,请稍后再试', // 允许覆盖Video.js无法播放媒体源时显示的默认信息。
        controlBar: false,
      },
      playing: true,
      playBtn: '',
    };
  },

  components: {
    videoPlayer,
  },
  created() {
  },
  methods: {
  },

};
</script>

<style lang="less" scoped>
  .videos {
    position: relative;

    /deep/ .vjs-big-play-button {
      position: absolute;
      width: 80px;
      height: 80px;
      border: none;
      background-color: transparent;
      left: 40%;
      top: 40%;
      content: none;

      .vjs-icon-placeholder {
        font-size: 100px;
        color: rgba(255, 255, 255, 0.7);
      }
    }
    /deep/ .video-js {
      height: calc(100vh - 50px);
    }
  }
</style>

3.VideoList视频列表组件的实现
代码如下:

<template>
  <div class="video-list">
    <!-- 视频内容 -->
    <swiper :options="swiperOptions">
      <swiper-slide v-for="(item,index) in dataList" :key="index">
        <div style="height: 100%;width: 100%;margin: 0 auto">
          <Videos :video="item" ref="videos" :index="index"></Videos>
        </div>
        <div class="info-wrap">
          <info-bar></info-bar>
        </div>
        <div class="rightbar_wrap">
          <right-bar @changeCom="showComs"></right-bar>
        </div>
      </swiper-slide>
    </swiper>
  </div>
</template>

<script>
import Videos from './Videos.vue';// 视频组件

export default {
  name: 'VideoList',
  props: ['dataList'],
  components: {
    Videos,
  },
  data() {
    return {
      // 是否弹出评论信息
      showComment: false,
      swiperOptions: {
        direction: 'vertical',
        grabCursor: true,
        setWrapperSize: true,
        autoHeight: true,
        slidesPerView: 1,
        mousewheel: true,
        mousewheelControl: true,
        height: window.innerHeight - 50,
        resistanceRatio: 0,
        observeParents: true,
        on: {
        },
      },
      page: 1, // 标识翻页
    };
  },
  methods: {
};
</script>

<style lang="less" scoped>
.video-list {
  height: 100%;
  position: relative;

  /deep/ .swiper-container {
    height: 100%;
    display: flex;
    .swiper-slide {
      height: 100%;
      display: flex;
      justify-content: center;
      align-items: center;
    }
  }

  .info-wrap {
    position: absolute;
    left: 0;
    bottom: 10px;
  }

  .rightbar_wrap {
    position: absolute;
    box-sizing: border-box;
    right: 0;
    bottom: 0px;
    padding-top: 10px;
  }

  .comment-wrap {
    position: fixed;
    left: 0;
    bottom: 0;
    height: 500px;
    width: 100%;
    border-top-left-radius: 15px;
    border-top-right-radius: 15px;
    z-index: 999;
    padding: 10px;
    background-color: #f8f8ff;
    box-sizing: border-box;
    .comment-box {
      padding-bottom: 10px;
    }
    .comment-top {
      display: flex;
      align-items: center;
      font-weight: bold;
      font-size: 16px;
      .number {
        flex: 1;

        text-align: center;
      }

      .close {
        padding-right: 5px;
        color: #666;
      }
    }

    .comment-body {
      max-height: 400px;
      overflow: auto;
      margin-top: 15px;
      .comment-item {
        display: flex;
      }

      .sub-comment-item {
        display: flex;
        margin-left: 33px;
        margin-top: 10px;

        .re-name {
          padding: 0 10px;
          color: #686868;
        }
      }

      .user-pic {
        width: 33px;
        height: 33px;
        border-radius: 50%;
      }

      .item-info {
        margin-left: 10px;
        display: flex;
        flex: 1 auto;

        .replay {
          width: 90%;
        }

        .replay-des,
        .reply-name {
          font-size: 14px;
          line-height: 20px;
        }

        .name {
          color: #686868;
          font-size: 13px;
        }

        .time {
          color: #686868;
        }

        .zan {
          color: rgb(205, 205, 205);
          display: flex;

          .icon-xinaixin-fuben {
            font-size: 20px;
          }

          p {
            font-size: 15px;
          }
        }
      }

      .more {
        margin-left: 30px;
      }
    }

    .reply-input {
      width: 100%;
      height: 50px;
      border-top: 1px solid #d9d9d9;
      position: absolute;
      bottom: 0;
      left: 0;
      align-items: center;
      display: flex;
      background-color: #fff;
      input {
        line-height: 40px;
        width: 70%;
        padding: 0 10px;
      }

      input:focus {
        border: none;
      }

      .emoji {
        margin: 0 10px;
      }

      .emoji,
      .iconfont {
        font-size: 30px;
        color: #686868;
      }
    }
  }
}
</style>

渲染列表

1.渲染首页页面视频播放列表
页面结构如下:
在这里插入图片描述
代码如下:

/*
首页
author:enjsky.g
time:2021-04-29
*/
<template>
  <div class="home-content">
    <topBar></topBar>
    <router-view  :dataList="videos"></router-view>
  </div>
</template>

<script>
import topBar from '@/common/components/top/TopBar.vue'; // 顶部导航组件

export default {
  name: 'Index',
  data() {
    return {
      videos: [// 视频数据
        {
          id: '1',
          // eslint-disable-next-line global-require
          url: require('../../../public/videos/index/01.mp4'),
          comment: [
          ],
        },
        {
          id: '2',
          // eslint-disable-next-line global-require
          url: require('../../../public/videos/index/02.mp4'),
        },
        {
          id: '3',
          url: 'http://video.jishiyoo.com/161b9562c780479c95bbdec1a9fbebcc/8d63913b46634b069e13188b03073c09-d25c062412ee3c4a0758b1c48fc8c642-ld.mp4',
        },
        {
          id: '4',
          // eslint-disable-next-line global-require
          url: require('../../../public/videos/index/03.mp4'),
        },
      ],
    };
  },
  components: {
    topBar,
  },
  mounted() {
    this.$router.push({ path: 'reVidelList' });
  },
};
</script>

<style lang="less" scoped>
.home-content {
  background: #000;
  // height: 100vh;
}
</style>

2.渲染推荐页面视频播放列表
页面结构如下:
在这里插入图片描述
代码如下:

<template>
  <div class="recommend">
    <router-view :dataList="videos"></router-view>
  </div>
</template>

<script>
export default {
  name: 'Recommend',
  data() {
    return {
      videos: [// 视频数据
        {
          id: '1',
          // eslint-disable-next-line global-require
          url: require('../../../public/videos/index/01.mp4'),
        },
        {
          id: '2',
          // eslint-disable-next-line global-require
          url: require('../../../public/videos/index/02.mp4'),
        },
        {
          id: '3',
          url: 'http://video.jishiyoo.com/161b9562c780479c95bbdec1a9fbebcc/8d63913b466

以上是关于vue.js项目实战运用篇之抖音视频APP-第五节:视频播放列表组件功能的主要内容,如果未能解决你的问题,请参考以下文章

vue.js项目实战运用篇之抖音视频APP-第十五节: 朋友页面功能

vue.js项目实战运用篇之抖音视频APP-第十五节: 朋友页面功能

vue.js项目实战运用篇之抖音视频APP-第八节: 视频播放功能

vue.js项目实战运用篇之抖音视频APP-第一节:项目环境搭建

vue.js项目实战运用篇之抖音视频APP-第十节: 评论列表功能

vue.js项目实战运用篇之抖音视频APP-第十节: 评论列表功能