首页 > 技术文章 > Vue项目搭建

pankypan 2019-08-05 08:10 原文

1. 项目分析

首页
	导航、登录注册栏、轮播图、地板导航
登录注册
	选项卡
免费课
	课程分类、筛选、课程列表
免费课详情
	课程封面视频、优惠活动倒计时、选项卡
我的购物车
	全选、商品价格统计
购买结算
	
购买成功
	
我的订单
	
课时播放页面
	

2. 项目搭建

2.1 创建项目目录

cd 项目目录
vue init webpack luffy

例如,我要把项目保存在桌面下 ~/Desktop/luffy ,可以如下操作:

cd Desktop
vue init webpack luffy

效果:

1556413886156

根据需要在生成项目时,我们选择对应的选项。

1556413914975

根据上面的提示,我们已经把vue项目构建好了,接下来我们可以在pycharm编辑器中把项目打开并根据上面黄色提示,运行测试服务器。

1556413966065

打开项目已经,在pycharm的终端下运行vue项目,查看效果。

npm run dev

1556414060937

接下来,我们根据终端上效果显示的对应地址来访问项目(如果有多个vue项目在运行,8080端口被占据了,服务器会自动改端口,所以根据自己实际在操作中看到的地址来访问。)

访问:http://localost:8080

1552440150350

2.2 初始化项目

清除默认的HelloWorld.vue组件和APP.vue中的默认模板代码和默认样式

1556414352611

<template>
  <div id="app">
  </div>
</template>

<script>

export default {
  name: 'App',
  components: {
  }
}
</script>

<style>
</style>

修改后效果:

1552458440851

接下来,我们可以查看效果了,一张白纸~

1556414476287

2.3 安装路由vue-router

2.3.1 下载路由组件

npm i vue-router -S

执行效果:

1556414629058

2.3.2 配置路由

2.3.2.1 初始化路由对象

在src目录下创建router路由目录,在router目录下创建index.js路由文件

效果:

1556415543613

index.js路由文件中,编写初始化路由对象的代码 .

import Vue from "vue"
import Router from "vue-router"

// 这里导入可以让让用户访问的组件

Vue.use(Router);

export default new Router({
  // 设置路由模式为‘history’,去掉默认的#
  mode: "history",
  routes:[
    // 路由列表

  ]
})

2.3.2.2 注册路由信息

打开main.js文件,把router路由规则对象注册到vue中.

1556415594925

代码:

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router/index';

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  components: { App },
  template: '<App/>'
});

2.3.2.3 在视图中显示路由对应的内容

在App.vue组件中,添加显示路由对应的内容。

1556415832883

代码:

<template>
  <div id="app">
    <router-view/>
  </div>
</template>

<script>
export default {
  name: 'App',
  components: {

  }
}
</script>

<style>

</style>


3. 引入ElementUI

对于前端页面布局,我们可以使用一些开源的UI框架来配合开发,Vue开发前端项目中,比较常用的就是ElementUI了。

ElementUI是饿了么团队开发的一个UI组件框架,这个框架提前帮我们提供了很多已经写好的通用模块,我们可以在Vue项目中引入来使用,这个框架的使用类似于我们前面学习的bootstrap框架,也就是说,我们完全可以把官方文档中的组件代码拿来就用,有定制性的内容,可以直接通过样式进行覆盖修改就可以了。

1552501300174

中文官网:http://element-cn.eleme.io/#/zh-CN

文档快速入门:http://element-cn.eleme.io/#/zh-CN/component/quickstart

3.1 快速安装ElementUI

项目根目录执行以下命令:

npm i element-ui -S

上面的命令等同于 npm install element-ui --save

执行命令效果:

1556417812874

3.2 配置ElementUI到项目中

在main.js中导入ElementUI,并调用。代码:

// elementUI 导入
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
// 调用插件
Vue.use(ElementUI);

效果:

1552501156871

成功引入了ElementUI以后,接下来我们就可以开始进入前端页面开发,首先是首页。

4. 首页

首页采用了上下页面布局,首页是导航栏、轮播图。。。脚部等几个小模块。所以我们可以把首页作为一个组件进行开发,然后把首页的这些小模块作为单独的组件来进行开发。

4.1 创建首页组件

在src/components目录下创建文件 Home.vue

代码:

<template>
  <div id="home">
    首页
  </div>
</template>

<script>
export default {
  name:"Home",
  data(){
    return {

    }
  }
}
</script>

<style scoped>

</style>


效果:

1556415917941

4.1.1 创建首页对应的路由

在router/index.js中引入Home组件,并设置Home组件作为首页路由。

代码:

import Vue from "vue"
import Router from "vue-router"

// 后面这里引入可以被用户访问的页面组件
import Home from "../components/Home"

Vue.use(Router);

export default new Router({
  // 路由跳转模式,注意使用 history
  mode: "history",

  // 路由规则
  routes:[
    {
      // name:"路由别名",
      name:"Home",
      // path: "路由地址",
      path: "/",
      // component: 组件类名,
      component: Home,
    },{
      // name:"路由别名",
      name:"Home",
      // path: "路由地址",
      path: "/home",
      // component: 组件类名,
      component: Home,
    },
  ]
})


效果:

1556416079117

4.2 开发导航子组件

经过前面的观察,可以发现导航不仅在首页出现,其他页面也有,所以对于这些不同页面中公共的内容,可以创建一个单独的组件目录存放。

1552501540495

创建src/components/common/Header.vue目录路径,编写代码:

<template>

</template>

<script>
  export default {
    name: "Header",
    data(){
      return {
        
      };
    }
  }
</script>

<style scoped>

</style>

效果:

1552501465055

4.2.1 在首页引入导航组件

代码:

<template>
  <div class="home">
    <Header/>
  </div>
</template>

<script>
  import Header from "./common/Header"
  export default {
    name: "Home",
    data(){
      return {

      };
    },
    components:{
      Header,
    }
  }
</script>

<style scoped>

</style>


效果:

1552502367059

接下来,我们就可以在组件中参考ElementUI文档来进行样式开发了。

1552503046597

Header的子组件代码:

<template>
  <div class="header">
    <el-container>
      <el-header>
        <el-row>
          <el-col class="logo" :span="3">
            <a href="/">
              <img src="@/assets/head-logo.svg" alt="">
            </a>
          </el-col>
          <el-col class="nav" :span="16">
              <el-row>
                <el-col :span="3"><router-link to="/">免费课</router-link></el-col>
                <el-col :span="3"><router-link to="/">轻课</router-link></el-col>
                <el-col :span="3"><router-link to="/">学位课</router-link></el-col>
                <el-col :span="3"><router-link to="/">题库</router-link></el-col>
                <el-col :span="3"><router-link to="/">教育</router-link></el-col>
              </el-row>
          </el-col>
          <el-col class="login-bar" :span="5">
            <el-row>
              <el-col class="cart-ico" :span="9">
                <router-link to="">
                  <b class="goods-number">0</b>
                  <img class="cart-icon" src="@/assets/cart.svg" alt="">
                  <span>购物车</span>
                </router-link>
              </el-col>
              <el-col class="study" :span="8" :offset="2"><router-link to="">学习中心</router-link></el-col>
              <el-col class="member" :span="5">
                <el-menu class="el-menu-demo" mode="horizontal">
                  <el-submenu index="2">
                    <template slot="title"><router-link to=""><img src="@/assets/logo@2x.png" alt=""></router-link></template>
                    <el-menu-item index="2-1">我的账户</el-menu-item>
                    <el-menu-item index="2-2">我的订单</el-menu-item>
                    <el-menu-item index="2-3">我的优惠卷</el-menu-item>
                    <el-menu-item index="2-3">退出登录</el-menu-item>
                  </el-submenu>
                </el-menu>
              </el-col>
            </el-row>
          </el-col>
        </el-row>
      </el-header>
    </el-container>
  </div>
</template>

<script>
  export default {
    name: "Header",
    data(){
      return {
        // 设置一个登录标识,表示是否登录
        token: false,
      };
    }
  }
</script>

<style scoped>
  .header{
    box-shadow: 0 0.5px 0.5px 0 #c9c9c9;
  }
  .header .el-container{
    width: 1200px;
    margin: 0 auto;
  }
  .el-header{
    height: 80px!important;
    padding:0;
  }
  .logo{

  }
  .logo img{
    padding-top: 22px;
  }

  .nav{
    margin-top: 22px;
  }

  .nav .el-col a{
    display: block;
    text-align: center;
    padding-bottom: 16px;
    padding-left: 5px;
    padding-right: 5px;
    position: relative;
    font-size: 16px;
  }

  .login-bar{
    margin-top: 22px;
  }
  .cart-ico{
    position: relative;
    border-radius: 17px;
  }
  .cart-ico:hover{
    background: #f0f0f0;
  }
  .goods-number{
    width: 16px;
    height: 16px;
    line-height: 17px;
    font-size: 12px;
    color: #fff;
    text-align: center;
    background: #fa6240;
    border-radius: 50%;
    transform: scale(.8);
    position: absolute;
    left: 16px;
    top: -1px;
  }
  .cart-icon{
    width: 15px;
    height: auto;
    margin-left: 6px;
  }
  .cart-ico span{
    margin-left: 12px;
  }
  .member img{
    width: 26px;
    height: 26px;
    border-radius: 50%;
    display: inline-block;
  }
  .member img:hover{
    border: 1px solid yellow;
  }

</style>


App.vue,中设置一些公共样式的代码:

<style>
  body{
    padding: 0;
    margin:0;
  }
  a{
    text-decoration: none;
    color: #4a4a4a;
  }
  a:hover{
    color: #000;
  }
  .header .el-menu li .el-submenu__title{
    height: 26px!important;
    line-height: 26px!important;
  }
  .el-menu--popup{
    min-width: 140px;
  }
</style>

Home组件中引入使用Header子组件,代码无需改变,直接访问效果:

1556423948867

4.3 开发轮播图子组件

1552503138518

4.3.1 创建Banner.vue组件文件

代码:

<template>
  <div class="banner">

  </div>
</template>

<script>
  export default {
    name:"Banner",
    data(){
      return {};
    }
  }
</script>

<style scoped>

</style>


1552532166152

4.3.1 在Home组件中引入Banner子组件

<template>
  <div class="home">
    <Header/>
    <Banner/>
  </div>
</template>

<script>
  import Header from "./common/Header"
  import Banner from "./common/Banner"
  export default{
    name:"Home",
    data(){
      return {};
    },
    components:{
      Header,
      Banner,
    }
  }
</script>

<style scoped>
.home{
  padding-top: 80px;
}
</style>


效果:

1552532278649

接下来,在ElementUI中有对应的轮播图[跑马灯]效果,可以直接提取过来使用。

1556424098873

注意,图片保存到static目录下。保存在assets目录下的图片等同于保存在static/img目录下。

1556424903235

对于图片的使用,如果是vue代码中直接要使用的图片,可以保存accets目录下,如果是第三方插件要使用到的图片,需要保存在static目录下。其实本质上来说,所有的图片都是保存在static目录下的,而assets目录下的内容,最终被vue解析成地址的时候,也是在static目录的.

Banner.vue组件,代码:

<template>
  <div class="banner">
      <el-carousel trigger="click" height="506px">
        <el-carousel-item v-for="banner in banner_list">
          <a :href="banner.link"><img width="100%" :src="banner.img" alt=""></a>
        </el-carousel-item>
      </el-carousel>
  </div>
</template>

<script>
  export default {
    name:"Banner",
    data(){
      return {
        banner_list:[
          {link:"http://www.baidu.com",img:"/static/banner/1.png"},
          {link:"http://www.baidu.com",img:"/static/banner/2.png"},
          {link:"http://www.baidu.com",img:"/static/banner/3.png"},
        ]
      };
    }
  }
</script>

<style scoped>

</style>


效果:

1552533179082

4.5 页面脚部

4.5.1 创建脚部组件文件

1552535310891

代码:

<template>
  <el-container>

  </el-container>
</template>

<script>
  export default {
    name:"Footer",
    data(){
      return {}
    }
  }
</script>


<style scoped>

</style>


4.5.2 在Home组件中引入Footer组件

Home组件代码:

<template>
  <div class="home">
    <Header/>
    <Banner/>
    <Footer/>
  </div>
</template>

<script>
  import Header from "./common/Header"
  import Banner from "./common/Banner"
  import Footer from "./common/Footer"
  export default{
    name:"Home",
    data(){
      return {};
    },
    components:{
      Header,
      Banner,
      Footer,
    }
  }
</script>

<style scoped>
.home{
  padding-top: 80px;
}
</style>


效果:

1552535407021

4.5.3 编写脚部样式

<template>
  <div class="footer">
    <el-container>
      <el-row>
        <el-col :span="4"><router-link to="">关于我们</router-link></el-col>
        <el-col :span="4"><router-link to="">联系我们</router-link></el-col>
        <el-col :span="4"><router-link to="">商务合作</router-link></el-col>
        <el-col :span="4"><router-link to="">帮助中心</router-link></el-col>
        <el-col :span="4"><router-link to="">意见反馈</router-link></el-col>
        <el-col :span="4"><router-link to="">新手指南</router-link></el-col>
        <el-col :span="24"><p class="copyright">Copyright © luffycity.com版权所有 | 京ICP备17072161号-1</p></el-col>
      </el-row>
    </el-container>
  </div>
</template>

<script>
  export default {
    name:"Footer",
    data(){
      return {}
    }
  }
</script>


<style scoped>
.footer{
  width: 100%;
  height: 128px;
  background: #25292e;
}
.footer .el-container{
  width: 1200px;
  margin: auto;
}
.footer .el-row {
  align-items: center;
  padding: 0 200px;
  padding-bottom: 15px;
  width: 100%;
  margin-top: 38px;
}
.footer .el-row a{
  color: #fff;
  font-size: 14px;
}
.footer .el-row .copyright{
  text-align: center;
  color: #fff;
  font-size: 14px;
}
</style>


效果:

1556425996044

首页的三大块我们已经完成了,但是我们开始新的页面出现之前,我们需要把链接补充上, 新增课程的导航链接.

接下来,我们就可以创建免费课的组件.

4.6 固定头部

App.vue

<style>
  body{
    padding: 0;
    margin:0;
    margin-top: 80px;
  }
  
</style>

Header.vue,代码:

<style scoped>
  .header{
    top:0;
    left:0;
    right:0;
    margin: auto;
    background-color: #fff;
    height: 80px;
    z-index: 1000;
    position: fixed;
    box-shadow: 0 0.5px 0.5px 0 #c9c9c9;
  }

</style>


调整轮播图左右两边的按钮

注意,style标签中要设置全局样式,所以不需要scoped

Banner.vue

<style>
.el-carousel__arrow{
  width: 100px!important;
  height: 100px!important;
}
.el-icon-arrow-left{
  font-size: 35px;
  margin-left: 50px;
}
.el-carousel__arrow--left{
  left: -50px;
}
</style>

5. 免费课

在组件目录components下创建Course.vue组件文件,代码如下:

<template>
  <div class="course">

  </div>
</template>

<script>
export default {
  name: "Course",
  data(){
    return {

    }
  },
}
</script>


<style scoped>
  
</style>


5.1 在routers/index.js路由中注册路由

import Vue from "vue"
import Router from "vue-router"

// 导入可以被用户访问的组件
import Home from "@/components/Home"
import Course from "@/components/Course"

Vue.use(Router);

export default new Router({
  mode: "history",
  routes:[
    // 路由列表
    {
      path: "/",
      name: "Home",
      component:Home,
    },
    {
      path: "/home",
      name: "Home",
      component:Home,
    },
    {
      path: "/course",
      name: "Course",
      component:Course,
    },

  ]
})


5.2 完成免费课课程列表

5.2.2 文件代码结构

Course.vue,代码:

<template>
  <div class="course">
    <Header/>
    <div class="main">
      <!-- 筛选功能 -->
      <div class="top">

      </div>
      <!-- 课程列表 --->
      <div class="list">

      </div>
    </div>
    <Footer/>
  </div>
</template>

<script>
import Header from "./common/Header"
import Footer from "./common/Footer"
export default {
  name: "Course",
  data(){
    return {

    }
  },
  components:{Header,Footer}
}
</script>

<style scoped>

</style>

5.2.3 筛选条件的样式实现

<template>
  <div class="courses">
    <Header/>
    <div class="main">
      <!--filter function-->
      <div class="top">
        <ul class="condition condition1">
          <li class="cate-condition">课程分类</li>
          <li class="item current">全部</li>
          <li class="item">Python</li>
          <li class="item">Linux运维</li>
          <li class="item">开发工具</li>
          <li class="item">Go语言</li>
          <li class="item">机器学习</li>
          <li class="item">技术生涯</li>
        </ul>
        <ul class="condition condition2">
          <li class="cate-condition">筛&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;选</li>
          <li class="item current">默认</li>
          <li class="item">人气</li>
          <li class="item price">价格</li>
          <li class="courses-length">共21个课程</li>
        </ul>
      </div>
      
      
      <!--courses list-->
      <div class="list">
      </div>
    </div>
    <Footer/>
  </div>
</template>


<script>
  import Header from "./common/Header"
  import Footer from "./common/Footer"


  export default{
    name: "Courses",
    data(){
      return {}},
    components:{
      Header,
      Footer,
    },
    methods:{}
  }
</script>


<style scoped>
  .main{
    width: 1100px;
    height: auto;
    margin: 0 auto;
    padding-top: 35px;
  }
  .main .top{
    margin-bottom: 35px;
    padding: 25px 30px 25px 20px;
    background: #ffffff;
    border-radius: 4px;
    box-shadow: 0 2px 4px 0 #f0f0f0;
  }
  .condition{
    border-bottom: 1px solid #333333;
    border-bottom-color: rgba(51, 51, 51, .05);
    padding-bottom: 18px;
    margin-bottom: 17px;
    overflow: hidden;
  }
  .condition li{
    float: left;
  }
  .condition .cate-condition{
    color: #888888;
    font-size: 16px;
  }
  .condition .item{
    padding: 6px 16px;
    line-height: 16px;
    margin-left: 14px;
    position: relative;
    transition: all .3s ease;
    cursor: pointer;
    color: #4a4a4a;
  }
  .condition1 .current{
    color: #ffc210;
    border: 1px solid #ffc210!important;
    border-radius: 30px;
  }
  .condition2 .current{
    color: #ffc210;
  }
  .condition .price::before{
    content: "";
    width: 0;
    border: 5px solid transparent;
    border-top-color: #ffc210;
    position: absolute;
    right: 0;
    bottom: 2.5px;
  }
  .condition .price::after{
  content: "";
    width: 0;
    border: 5px solid transparent;
    border-bottom-color: #d8d8d8;
    position: absolute;
    right: 0;
    top: 2.5px;
  }
  .condition2 .courses-length{
    float: right;
    font-size: 14px;
    color: #9b9b9b;
  }

</style>


App.vue针对列表标签进行初始化,代码:

ul{
    list-style: none;
    padding:0;
    margin:0;
  }
  

效果:

1556502578181

5.2.4 课程类表的样式实现和特效

<template>
  <div class="courses">
    <Header/>
    <div class="main">
      <!--filter function-->
      <div class="top">
        <ul class="condition condition1">
          <li class="cate-condition">课程分类</li>
          <li class="item current">全部</li>
          <li class="item">Python</li>
          <li class="item">Linux运维</li>
          <li class="item">开发工具</li>
          <li class="item">Go语言</li>
          <li class="item">机器学习</li>
          <li class="item">技术生涯</li>
        </ul>
        <ul class="condition condition2">
          <li class="cate-condition">筛&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;选</li>
          <li class="item current">默认</li>
          <li class="item">人气</li>
          <li class="item price">价格</li>
          <li class="courses-length">共21个课程</li>
        </ul>
      </div>


      <!--courses list-->
      <div class="list">
        <ul>
          <li class="course-item">
            <div class="course-cover">
              <img src="../../static/courses/1.jpeg" alt=""/>
            </div>
            <div class="course-info">
              <div class="course-title">
                <h3>Python开发21天入门</h3>
                <span>69939人已经加入学习</span>
              </div>
              <p class="teacher">
                <span class="info">Alex 金角大王 老男孩Python教学总监</span>
                <span class="lesson">共154课时/更新完成</span>
              </p>
              <ul class="lesson-list">
                <li>
                  <p class="lesson-title">01 | 常用模块学习-模块的种类和导入方法</p>
                  <span class="free">免费</span>
                </li>
                 <li>
                  <p class="lesson-title">02 | 编程语言介绍(三)高级语言</p>
                  <span class="free">免费</span>
                </li>
                 <li>
                  <p class="lesson-title">03 | 编程语言介绍(一)</p>
                  <span class="free">免费</span>
                </li>
                 <li>
                  <p class="lesson-title">04 | 课程介绍(二)-Python与其他语言的区别</p>
                  <span class="free">免费</span>
                </li>
              </ul>
              <div class="buy-info">
                <span class="discount">限时免费</span>
                <span class="present-price">¥0.00元</span>
                <span class="original-price">原价:9.00元</span>
                <span class="buy-now">立即购买</span>
              </div>
            </div>
          </li>
        </ul>
      </div>
    </div>
    <Footer/>
  </div>
</template>


<script>
  import Header from "./common/Header"
  import Footer from "./common/Footer"


  export default{
    name: "Courses",
    data(){
      return {}},
    components:{
      Header,
      Footer,
    },
    methods:{}
  }
</script>


<style scoped>
  .main{
    width: 1100px;
    height: auto;
    margin: 0 auto;
    padding-top: 35px;
  }
  .main .top{
    margin-bottom: 35px;
    padding: 25px 30px 25px 20px;
    background: #ffffff;
    border-radius: 4px;
    box-shadow: 0 2px 4px 0 #f0f0f0;
  }
  .condition{
    border-bottom: 1px solid #333333;
    border-bottom-color: rgba(51, 51, 51, .05);
    padding-bottom: 18px;
    margin-bottom: 17px;
    overflow: hidden;
  }
  .condition li{
    float: left;
  }
  .condition .cate-condition{
    color: #888888;
    font-size: 16px;
  }
  .condition .item{
    padding: 6px 16px;
    line-height: 16px;
    margin-left: 14px;
    position: relative;
    transition: all .3s ease;
    cursor: pointer;
    color: #4a4a4a;
  }
  .condition1 .current{
    color: #ffc210;
    border: 1px solid #ffc210!important;
    border-radius: 30px;
  }
  .condition2 .current{
    color: #ffc210;
  }
  .condition .price::before{
    content: "";
    width: 0;
    border: 5px solid transparent;
    border-top-color: #ffc210;
    position: absolute;
    right: 0;
    bottom: 2.5px;
  }
  .condition .price::after{
  content: "";
    width: 0;
    border: 5px solid transparent;
    border-bottom-color: #d8d8d8;
    position: absolute;
    right: 0;
    top: 2.5px;
  }
  .condition2 .courses-length{
    float: right;
    font-size: 14px;
    color: #9b9b9b;
  }


  .course-item{
    background: #ffffff;
    padding: 20px 30px 20px 20px;
    margin-bottom: 35px;
    border-radius: 2px;
    cursor: pointer;
    box-shadow: 2px 3px 16px rgba(0, 0, 0, .1);
    transition: all .2s ease;
    overflow: hidden;
  }
  .course-cover{
    width: 423px;
    height: 210px;
    margin-right: 30px;
    float: left;
  }
  .course-info{
    width: 597px;
    float: left;
  }
  .course-title{
    margin-bottom: 8px;
    overflow: hidden;
  }
  .course-title h3{
    font-size: 26px;
    color: #333333;
    float: left;
  }
  .course-title span{
    float: right;
    font-size: 14px;
    color: #9b9b9b;
    margin-top: 12px;
    text-indent: 1em;
    background: url("../assets/people.svg") no-repeat 0px 3px;
  }
  .teacher{
    justify-content: space-between;
    font-size: 14px;
    color: #9b9b9b;
    margin-bottom: 14px;
    padding-bottom: 14px;
    border-bottom: 1px solid #333333;
    border-bottom-color: rgba(51, 51, 51, .05);
  }
  .teacher .lesson{
    float: right;
  }
  .lesson-list{
    overflow: hidden;
  }
  .lesson-list li{
    width: 49%;
    margin-bottom: 15px;
    cursor: pointer;
    float: left;
    margin-right: 1%;
  }
  .lesson-list li .player{
    width: 16px;
    height: 16px;
    vertical-align: text-bottom;
  }
  .lesson-list li .lesson-title{
    display: inline-block;
    max-width: 227px;
    text-overflow: ellipsis;
    color: #666666;
    overflow: hidden;
    white-space: nowrap;
    font-size: 14px;
    vertical-align: text-bottom;
    text-indent: 1.5em;
    background: url("../../static/2.svg") no-repeat 0px 3px;
  }
  .lesson-list .free{
    width: 34px;
    height: 20px;
    color: #fd7b4d;
    margin-left: 10px;
    border-radius: 2px;
    border: 1px solid #fd7b4d;
    text-align: center;
    font-size: 13px;
    white-space: nowrap;
  }

.lesson-list li:hover .lesson-title{
    color: #ffc210;
    background-image: url(../../static/2.svg);
}
.lesson-list li:hover .free{
    border-color: #ffc210;
    color: #ffc210;
}

.buy-info .discount{
    padding: 0px 10px;
    font-size: 16px;
    color: #fff;
    display: inline-block;
    height: 36px;
    text-align: center;
    margin-right: 8px;
    background: #fa6240;
    border: 1px solid #fa6240;
    border-radius: 10px 0 10px 0;
    line-height: 36px;
}
.present-price{
    font-size: 24px;
    color: #fa6240;
}
.original-price{
    text-decoration: line-through;
    font-size: 14px;
    color: #9b9b9b;
    margin-left: 10px;
}
.buy-now{
    width: 120px;
    height: 38px;
    background: transparent;
    color: #fa6240;
    font-size: 16px;
    border: 1px solid #fd7b4d;
    border-radius: 3px;
    transition: all .2s ease-in-out; /* 过渡动画 */
    float: right;
    margin-top: 5px;
}
.buy-now:hover{
    color: #fff;
    background: #ffc210;
    border: 1px solid #ffc210;
    cursor: pointer;
}
</style>

App.vue

<style>
  body,h3,ul,p{
    padding: 0;
    margin:0;
    font-weight: normal;
  }
  body{
    margin-top: 80px;
  }
  a{
    text-decoration: none;
    color: #4a4a4a;
  }
  a:hover{
    color: #000;
  }

  ul{
    list-style: none;
  }

  img{
    width: 100%;
  }

  .header .el-menu li .el-submenu__title{
    height: 26px!important;
    line-height: 26px!important;
  }
  .el-menu--popup{
    min-width: 140px;
  }

</style>

6. 针对页面头部部分增加高亮和登录按钮

6.1 增加当前页面导航高亮效果

<template>
<div class="header">
  <el-container>
    <el-header>
      <el-row>
        <el-col class="logo" :span="3">
          <img src="@/assets/head-logo.svg" alt=""/>
        </el-col>
        <el-col class="nav" :span="16">
          <el-row>
            <!-- 加入current 实现高亮效果 -->
            <el-col :span="3"><router-link class="current" to="/home">免费课</router-link></el-col>
            <el-col :span="3"><router-link to="/">轻课</router-link></el-col>
            <el-col :span="3"><router-link to="/">学位课</router-link></el-col>
            <el-col :span="3"><router-link to="/">题库</router-link></el-col>
            <el-col :span="3"><router-link to="/">教育</router-link></el-col>
          </el-row>
        </el-col>
        <el-col class="login-bar" :span="5">
          <el-row>
            <el-col class="cart-ico" :span="9">
              <router-link to="">
              <b class="goods-number">0</b>
              <img class="cart-icon" src="@/assets/download.svg" alt=""/>
              <span>购物车</span>
              </router-link>
            </el-col>
            <el-col class="study" :span="8" :offset="2"><router-link to="">学习中心</router-link></el-col>
            <el-col class="member" :span="5">
              <el-menu class="el-menu-demo" mode="horizontal">
                <el-submenu index="2">
                  <template slot="title"><router-link to=""><img src="@/assets/logo@2x.png" alt=""/></router-link></template>
                  <el-menu-item index="2-1">我的账户</el-menu-item>
                  <el-menu-item index="2-2">我的订单</el-menu-item>
                  <el-menu-item index="2-3">我的优惠券</el-menu-item>
                  <el-menu-item index="2-4">退出登录</el-menu-item>
                </el-submenu>
              </el-menu>
            </el-col>
          </el-row>
        </el-col>
      </el-row>
    </el-header>
  </el-container>
</div>
</template>

<script>
  export default {
    name: "Header",
    data(){
      return {};
    }
  }
</script>

<style scoped>
  .header{
    top: 0;
    left: 0;
    right: 0;
    margin: auto;
    background-color: #ffffff;
    height: 80px;
    z-index: 1000;
    position: fixed;
    width: 100%;
    box-shadow: 0 0.5px 0.5px 0 #c9c9c9;
  }
  .header .el-container{
    width: 1200px;
    margin: 0 auto;
  }
  .el-header{
    height: 80px!important;
    padding: 0;
  }
  .logo img{
    padding-top: 17px;
  }
  .nav{
    margin-top: 22px;
  }
  .nav .el-col a{
    display: block;
    text-align: center;
    margin-left: 30px;
    padding-bottom: 16px;
    padding-left: 5px;
    padding-right: 5px;
    position: relative;
    font-size: 16px;
    text-decoration: none;
  }
  /* 加入current实现高亮效果 */
  .nav .el-col .current{
    color: #4a4a4a;
    border-bottom: 4px solid #ffc210;
  }
  .login-bar{
    margin-top: 22px;
  }
  .cart-ico{
    position: relative;
    border-radius: 17px;
  }
  .cart-ico:hover{
    background: #f0f0f0;
  }
  .goods-number{
    width: 16px;
    height: 16px;
    line-height: 17px;
    font-size: 12px;
    color: #ffffff;
    text-align: center;
    background: #fa6240;
    border-radius: 50%;
    transform: scale(.8);
    position: absolute;
    left: 16px;
    top: -1px;
  }
  .cart-icon{
    width: 15px;
    height: auto;
    margin-left: 6px;
  }
  .cart-ico span{
    margin-left: 12px;
  }
  .cart-ico a{
    text-decoration: none;
  }
  .member img{
    width: 26px;
    height: 26px;
    border-radius: 50%;
    display: inline-block;
  }
  .member img:hover{
    border: 1px solid yellow;
  }
  .study a{
    text-decoration: none;
  }
</style>

6.2 根据登录状态显示登录注册按钮

<template>
  <div class="header">
    <el-container>
      <el-header>
        <el-row>
          <el-col class="logo" :span="3">
            <a href="/">
              <img src="@/assets/head-logo.svg" alt="">
            </a>
          </el-col>
          <el-col class="nav" :span="16">
              <el-row>
                <el-col :span="3"><router-link class="current" to="/">免费课</router-link></el-col>
                <el-col :span="3"><router-link to="/">轻课</router-link></el-col>
                <el-col :span="3"><router-link to="/">学位课</router-link></el-col>
                <el-col :span="3"><router-link to="/">题库</router-link></el-col>
                <el-col :span="3"><router-link to="/">教育</router-link></el-col>
              </el-row>
          </el-col>
          <el-col class="login-bar" :span="5">
            <el-row v-if="token">
              <el-col class="cart-ico" :span="9">
                <router-link to="">
                  <b class="goods-number">0</b>
                  <img class="cart-icon" src="@/assets/cart.svg" alt="">
                  <span>购物车</span>
                </router-link>
              </el-col>
              <el-col class="study" :span="8" :offset="2"><router-link to="">学习中心</router-link></el-col>
              <el-col class="member" :span="5">
                <el-menu class="el-menu-demo" mode="horizontal">
                  <el-submenu index="2">
                    <template slot="title"><router-link to=""><img src="@/assets/logo@2x.png" alt=""></router-link></template>
                    <el-menu-item index="2-1">我的账户</el-menu-item>
                    <el-menu-item index="2-2">我的订单</el-menu-item>
                    <el-menu-item index="2-3">我的优惠卷</el-menu-item>
                    <el-menu-item index="2-3">退出登录</el-menu-item>
                  </el-submenu>
                </el-menu>
              </el-col>
            </el-row>
            <el-row v-else>
              <el-col class="cart-ico" :span="9">
                <router-link to="">
                  <img class="cart-icon" src="@/assets/cart.svg" alt="">
                  <span>购物车</span>
                </router-link>
              </el-col>
              <el-col :span="10" :offset="5">
                <span class="register">
                  <router-link to="/login">登录</router-link>
                  &nbsp;&nbsp;|&nbsp;&nbsp;
                  <router-link to="/register">注册</router-link>
                </span>
              </el-col>
            </el-row>
          </el-col>
        </el-row>
      </el-header>
    </el-container>
  </div>
</template>

<script>
  export default {
    name: "Header",
    data(){
      return {
        // 设置一个登录标识,表示是否登录
        token: false,
      };
    }
  }
</script>

<style scoped>
  .header{
    top:0;
    left:0;
    right:0;
    margin: auto;
    background-color: #fff;
    height: 80px;
    z-index: 1000;
    position: fixed;
    box-shadow: 0 0.5px 0.5px 0 #c9c9c9;
  }
  .header .el-container{
    width: 1200px;
    margin: 0 auto;
  }
  .el-header{
    height: 80px!important;
    padding:0;
  }
  .logo{

  }
  .logo img{
    padding-top: 22px;
  }

  .nav{
    margin-top: 22px;
  }

  .nav .el-col a{
    display: inline-block;
    text-align: center;
    padding-bottom: 16px;
    padding-left: 5px;
    padding-right: 5px;
    position: relative;
    font-size: 16px;
    margin-left: 20px;
  }

  .nav .el-col .current{
    color: #4a4a4a;
    border-bottom: 4px solid #ffc210;
  }

  .login-bar{
    margin-top: 22px;
  }
  .cart-ico{
    position: relative;
    border-radius: 17px;
  }
  .cart-ico:hover{
    background: #f0f0f0;
  }
  .goods-number{
    width: 16px;
    height: 16px;
    line-height: 17px;
    font-size: 12px;
    color: #fff;
    text-align: center;
    background: #fa6240;
    border-radius: 50%;
    transform: scale(.8);
    position: absolute;
    left: 16px;
    top: -1px;
  }
  .cart-icon{
    width: 15px;
    height: auto;
    margin-left: 6px;
  }
  .cart-ico span{
    margin-left: 12px;
  }
  .member img{
    width: 26px;
    height: 26px;
    border-radius: 50%;
    display: inline-block;
  }
  .member img:hover{
    border: 1px solid yellow;
  }

</style>

data数据中使用token控制显示登录和未登录状态的效果:

token:false

1552660186604

token: true

1552660243916

7. 购物车页面

在头部公共组件中打通购物车的链接地址,Header.vue

<span><router-link to="/cart">购物车</router-link></span>

7.1 创建购物车页面组件

在components/创建Cart .vue组件文件

<template>
    <div class="cart">
      <Header/>
      <Footer/>
    </div>
</template>

<script>
import Header from "./common/Header"
import Footer from "./common/Footer"
export default {
    name: "Cart",
    data(){
      return{

      }
    },
    components:{Header,Footer}
}
</script>

<style scoped>

</style>


7.2 注册路由地址

routers/index.js代码:

import Cart from "@/components/Cart"

export default new Router({
  // 路由跳转模式,注意使用 history
  mode: "history",

  // 路由规则
  routes:[
    。。。
    ,{
      name:"Cart",
      path: "/cart",
      component: Cart,
    },
  ]
})

7.3 显示表格数据

<template>
    <div class="cart">
      <Header/>
      <div class="main">
        <div class="cart-title">
          <h3>我的购物车 <span> 共2门课程</span></h3>
          <el-table :data="courseData" style="width:100%">
            <el-table-column type="selection" label="" width="87"></el-table-column>
            <el-table-column prop="title" label="课程" width="540"></el-table-column>
            <el-table-column prop="expire" label="有效期" width="216"></el-table-column>
            <el-table-column prop="price" label="单价" width="162"></el-table-column>
            <el-table-column label="操作" width="162"></el-table-column>
          </el-table>
        </div>
        <div calss="cart-info"></div>
      </div>
      <Footer/>
    </div>
</template>

<script>
import Header from "./common/Header"
import Footer from "./common/Footer"
export default {
    name: "Cart",
    data(){
      return{
        courseData:[
          {title:"课程标题一",expire:"2016",price:"12.00"},
          {title:"课程标题一",expire:"2016",price:"12.00"},
          {title:"课程标题一",expire:"2016",price:"12.00"},
          {title:"课程标题一",expire:"2016",price:"12.00"},
          {title:"课程标题一",expire:"2016",price:"12.00"},
          {title:"课程标题一",expire:"2016",price:"12.00"},
          {title:"课程标题一",expire:"2016",price:"12.00"},
          {title:"课程标题一",expire:"2016",price:"12.00"},
        ]
      }
    },
    components:{Header,Footer}
}
</script>

<style scoped>
.main{
  width: 1200px;
  margin: 0 auto;
  overflow: hidden; /* 解决body元素和标题之间的上下外边距的塌陷问题 */
}
.cart-title h3{
  font-size: 18px;
  color: #666;
  margin: 25px 0;
}
.cart-title h3 span{
  font-size: 12px;
  color: #d0d0d0;
  display: inline-block;
}
</style>

接下来, 我们需要在表格中输出其他的图片或者链接信息,在elementUI提供的表格组件中,我们可以使用template标签来完成.

            <el-table-column prop="title" label="课程" width="540">
              <template slot-scope="scope">
                <img src="../../static/course/1544059695.jpeg" alt="">
                <a href="">千台服务器管理系统开发实战</a>
              </template>
            </el-table-column>

7.4完善购物车中的数据展示

Cart.vue,代码:

<template>
    <div class="cart">
      <Header/>
      <div class="main">
        <div class="cart-title">
          <h3>我的购物车 <span> 共2门课程</span></h3>
        </div>
        <div class="cart-info">
          <el-table :data="courseData" style="width:100%">
            <el-table-column type="selection" label="" width="87"></el-table-column>
            <el-table-column label="课程" width="540">
              <template slot-scope="scope">
                <div class="course-box">
                  <img :src="scope.row.img" alt="">
                  {{scope.row.title}}
                </div>
              </template>
            </el-table-column>
            <el-table-column label="有效期" width="216">
              <template slot-scope="scope">
                <el-form ref="form" label-width="60px">
                  <el-form-item>
                    <el-select v-model="expire" placeholder="请选择有效期">
                      <el-option v-for="item in expire_list" :key="item.id" :label="item.title" :value="item.id"></el-option>
                    </el-select>
                  </el-form-item>
                </el-form>
              </template>
            </el-table-column>
            <el-table-column label="单价" width="162">
              <template slot-scope="scope">¥{{ scope.row.price }}</template>
            </el-table-column>
            <el-table-column label="操作" width="162">
              <a href="">删除</a>
            </el-table-column>
          </el-table>
        </div>
        <div class="cart-bottom">
          <div class="select-all"><el-checkbox>全选</el-checkbox></div>
          <div class="delete-any"><img src="../../static/img/ico3.png" alt="">删除</div>
          <div class="cart-bottom-right">
            <span class="total">总计:¥<span>0.0</span></span>
            <span class="go-pay">去结算</span>
          </div>
        </div>
      </div>
      <Footer/>
    </div>
</template>

<script>
import Header from "./common/Header"
import Footer from "./common/Footer"
export default {
    name: "Cart",
    data(){
      return{
        expire:3,
        expire_list:[
            {title:"一个月有效",id:1},
            {title:"两个月有效",id:2},
            {title:"三个月有效",id:3},
            {title:"永久有效",id:4},
        ],
        courseData:[
          {img:"../../static/course/1544059695.jpeg",title:"课程标题一",expire:"2016",price:"12.00"},
          {img:"../../static/course/1544059695.jpeg",title:"课程标题一",expire:"2016",price:"12.00"},
        ]
      }
    },
    components:{Header,Footer}
}
</script>

<style scoped>
.main{
  width: 1200px;
  margin: 0 auto;
  overflow: hidden; /* 解决body元素和标题之间的上下外边距的塌陷问题 */
}
.cart-title h3{
  font-size: 18px;
  color: #666;
  margin: 25px 0;
}
.cart-title h3 span{
  font-size: 12px;
  color: #d0d0d0;
  display: inline-block;
}
.course-box img{
    max-width: 175px;
    max-height: 115px;
    margin-right: 35px;
    vertical-align: middle;
}
.cart-bottom{
  overflow: hidden;
  height: 80px;
  background: #F7F7F7;
  margin-bottom: 300px;
  margin-top: 50px;
}
.select-all{
  float: left;
  margin-right: 58px;
  line-height: 80px;
}
.delete-any{
  cursor: pointer;
  float: left;
  line-height: 80px;
}
.delete-any img{
  width:18px;
  height: 18px;
  vertical-align: middle;
  padding-right: 15px;
}
.cart-bottom-right{
  float: right;
  text-align: right; /* 文本右对齐 */
}
.total{
  margin-right: 62px;
  font-size: 18px;
  color: #666;
}
.go-pay{
  outline: none;
  background: #ffc210;
  display: inline-block;
  padding: 27px 50px;
  font-size: 18px;
  cursor: pointer;
  color: #fff;
}
</style>


App.vue,增加修改css样式的代码:

  .el-checkbox__inner{
    width:16px;
    height: 16px;
    border: 1px solid #999;
  }
  .el-checkbox__inner:after{
    width: 6px;
    height: 8px;
  }
  .el-form-item__content{
    margin-left:0px!important;
    width: 120px;
  }

8.课程详情页

创建课程详情页的组件Detai.vue,基本代码结构:

<template>
    <div class="detail">
      <Header/>
      <div class="main">

      </div>
      <Footer/>
    </div>
</template>

<script>
import Header from "./common/Header"
import Footer from "./common/Footer"
export default {
    name: "Detail",
    data(){
      return {}
    },
    components:{
      Header,
      Footer,
    }
}
</script>

<style scoped>

</style>

在router/index.js中增加路由

import Detail from "@/components/Detail"

  // 路由规则
  routes:[
    ,{
      name:"Detail",
      path: "/detail",
      component: Detail,
    },
  ]
})


在课程列表页中的li里面新增一个router-link 跳转链接。

<template>
  <div class="course">
    <Header/>
    <div class="main">
      <!-- 筛选功能 -->
      <div class="top">
        <ul class="condition condition1">
          <li class="cate-condition">课程分类:</li>
          <li class="item current">全部</li>
          <li class="item">Python</li>
          <li class="item">Linux运维</li>
          <li class="item">Python进阶</li>
          <li class="item">开发工具</li>
          <li class="item">Go语言</li>
          <li class="item">机器学习</li>
          <li class="item">技术生涯</li>
        </ul>
        <ul class="condition condition2">
          <li class="cate-condition">筛&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;选:</li>
          <li class="item current">默认</li>
          <li class="item">人气</li>
          <li class="item price">价格</li>
          <li class="course-length">共21个课程</li>
        </ul>
      </div>
      <!-- 课程列表 --->
      <div class="list">
        <ul>
          <li class="course-item">
            <router-link to="/detail" class="course-link">
              <div class="course-cover">...
              <div class="course-info">...               
            </router-link>
          </li>
          ...../// 省略代码
</template>


<style scoped>
.course-link{
  overflow: hidden;
}
</style>

8.1课程基本信息展示

Detail.vue,代码:

<template>
    <div class="detail">
      <Header/>
      <div class="main">
        <div class="course-info">
          <div class="wrap-left"></div>
          <div class="wrap-right">
            <h3 class="name">Linux系统基础5周入门精讲</h3>
            <p class="data">23475人在学&nbsp;&nbsp;&nbsp;&nbsp;课程总时长:148课时/180小时&nbsp;&nbsp;&nbsp;&nbsp;难度:初级</p>
            <div class="sale-time">
              <p class="sale-type">限时免费</p>
              <p class="expire">距离结束:仅剩 01天 04小时 33分 <span class="second">08</span> 秒</p>
            </div>
            <p class="course-price">
              <span>活动价</span>
              <span class="discount">¥0.00</span>
              <span class="original">¥29.00</span>
            </p>
            <div class="buy">
              <div class="buy-btn">
                <button class="buy-now">立即购买</button>
                <button class="free">免费试学</button>
              </div>
              <div class="add-cart"><img src="@/assets/cart-yellow.svg" alt="">加入购物车</div>
            </div>
          </div>
        </div>
      </div>
      <Footer/>
    </div>
</template>

<script>
import Header from "./common/Header"
import Footer from "./common/Footer"
export default {
    name: "Detail",
    data(){
      return {}
    },
    components:{
      Header,
      Footer,
    }
}
</script>

<style scoped>
.main{
  background: #fff;
  padding-top: 30px;
}
.course-info{
  width: 1200px;
  margin: 0 auto;
  overflow: hidden;
}
.wrap-left{
  float: left;
  width: 690px;
  height: 388px;
  background-color: #000;
}
.wrap-right{
  float: left;
  position: relative;
  height: 388px;
}
.name{
  font-size: 20px;
  color: #333;
  padding: 10px 23px;
  letter-spacing: .45px;
}
.data{
  padding-left: 23px;
  padding-right: 23px;
  padding-bottom: 16px;
  font-size: 14px;
  color: #9b9b9b;
}
.sale-time{
  width: 464px;
  background: #fa6240;
  font-size: 14px;
  color: #4a4a4a;
  padding: 10px 23px;
  overflow: hidden;
}
.sale-type {
  font-size: 16px;
  color: #fff;
  letter-spacing: .36px;
  float: left;
}
.sale-time .expire{
  font-size: 14px;
  color: #fff;
  float: right;
}
.sale-time .expire .second{
  width: 24px;
  display: inline-block;
  background: #fafafa;
  color: #5e5e5e;
  padding: 6px 0;
  text-align: center;
}
.course-price{
  background: #fff;
  font-size: 14px;
  color: #4a4a4a;
  padding: 5px 23px;
}
.discount{
  font-size: 26px;
  color: #fa6240;
  margin-left: 10px;
  display: inline-block;
  margin-bottom: -5px;
}
.original{
  font-size: 14px;
  color: #9b9b9b;
  margin-left: 10px;
  text-decoration: line-through;
}
.buy{
  width: 464px;
  padding: 0px 23px;
  position: absolute;
  left: 0;
  bottom: 20px;
  overflow: hidden;
}
.buy .buy-btn{
  float: left;
}
.buy .buy-now{
  width: 125px;
  height: 40px;
  border: 0;
  background: #ffc210;
  border-radius: 4px;
  color: #fff;
  cursor: pointer;
  margin-right: 15px;
  outline: none;
}
.buy .free{
  width: 125px;
  height: 40px;
  border-radius: 4px;
  cursor: pointer;
  margin-right: 15px;
  background: #fff;
  color: #ffc210;
  border: 1px solid #ffc210;
}
.add-cart{
  float: right;
  font-size: 14px;
  color: #ffc210;
  text-align: center;
  cursor: pointer;
  margin-top: 10px;
}
.add-cart img{
  width: 20px;
  height: 18px;
  margin-right: 7px;
  vertical-align: middle;
}
</style>

效果:

1556533780731

8.2使用vue-video播放器

线上的路飞学城使用了AliPlayer阿里播放器。

我们本次项目使用vue-video播放器,是专门提供给vue项目使用。使用只需要完成四个步骤:

  1. 安装依赖
npm install vue-video-player --save

  1. 在main.js中注册加载组件
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from "./routers/index"

// ElementUI plugin
import ElementUI from "element-ui"
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(ElementUI);

// vue-video plugin
import 'video.js/dist/video-js.css';
import "vue-video-player/src/custom-theme.css";
import VideoPlayer from "vue-video-player";
Vue.use(VideoPlayer);

Vue.config.productionTip = false;

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  components: { App },
  template: '<App/>'
});

  1. 在课程详情页中的script标签配置播放器的参数,以下代码:
import {videoPlayer} from 'vue-video-player';

export default {
  data () {
    return {
      playerOptions: {
        playbackRates: [0.7, 1.0, 1.5, 2.0], // 播放速度
        autoplay: false, //如果true,则自动播放
        muted: false, // 默认情况下将会消除任何音频。
        loop: false, // 循环播放
        preload: 'auto', // 建议浏览器在<video>加载元素后是否应该开始下载视频数据。auto浏览器选择最佳行为,立即开始加载视频(如果浏览器支持)
        language: 'zh-CN',
        aspectRatio: '16:9', // 将播放器置于流畅模式,并在计算播放器的动态大小时使用该值。值应该代表一个比例 - 用冒号分隔的两个数字(例如"16:9"或"4:3")
        fluid: true, // 当true时,Video.js player将拥有流体大小。换句话说,它将按比例缩放以适应其容器。
        sources: [{
          type: "video/mp4",
          src: "http://img.ksbbs.com/asset/Mon_1703/05cacb4e02f9d9e.mp4" //你的视频地址(必填)
        }],
        poster: "../static/courses/675076.jpeg", //视频封面图
        width: document.documentElement.clientWidth,
        notSupportedMessage: '此视频暂无法播放,请稍后再试', //允许覆盖Video.js无法播放媒体源时显示的默认信息。
      }
    }
  },
  components: {
    videoPlayer
  },
  methods: {
    onPlayerPlay(player) {
      alert("play");
    },
    onPlayerPause(player){
      alert("pause");
    },
    player() {
      return this.$refs.videoPlayer.player
    }
  }
}

在html模板中调用video-player标签显示播放器

          <div class="warp-left" style="width: 690px;height: 388px;background-color: #000;">
            <video-player class="video-player vjs-custom-skin"
                 ref="videoPlayer"
                 :playsinline="true"
                 :options="playerOptions"
                 @play="onPlayerPlay($event)"
                 @pause="onPlayerPause($event)"
            >
            </video-player>
          </div>

效果:

1556538257873

集成了编辑器以后的课程详情页组件代码

<template>
    <div class="detail">
      <Header/>
      <div class="main">
        <div class="course-info">
          <div class="wrap-left">
            <video-player class="video-player vjs-custom-skin"
               ref="videoPlayer"
               :playsinline="true"
               :options="playerOptions"
               @play="onPlayerPlay($event)"
               @pause="onPlayerPause($event)"
            >
            </video-player>
          </div>
          <div class="wrap-right">
            <h3 class="name">Linux系统基础5周入门精讲</h3>
            <p class="data">23475人在学&nbsp;&nbsp;&nbsp;&nbsp;课程总时长:148课时/180小时&nbsp;&nbsp;&nbsp;&nbsp;难度:初级</p>
            <div class="sale-time">
              <p class="sale-type">限时免费</p>
              <p class="expire">距离结束:仅剩 01天 04小时 33分 <span class="second">08</span> 秒</p>
            </div>
            <p class="course-price">
              <span>活动价</span>
              <span class="discount">¥0.00</span>
              <span class="original">¥29.00</span>
            </p>
            <div class="buy">
              <div class="buy-btn">
                <button class="buy-now">立即购买</button>
                <button class="free">免费试学</button>
              </div>
              <div class="add-cart"><img src="@/assets/cart-yellow.svg" alt="">加入购物车</div>
            </div>
          </div>
        </div>
      </div>
      <Footer/>
    </div>
</template>

<script>
import Header from "./common/Header"
import Footer from "./common/Footer"

import {videoPlayer} from 'vue-video-player';

export default {
    name: "Detail",
    data(){
      return {
        playerOptions: {
          playbackRates: [0.7, 1.0, 1.5, 2.0], // 播放速度
          autoplay: false, //如果true,则自动播放
          muted: false, // 默认情况下将会消除任何音频。
          loop: false, // 循环播放
          preload: 'auto',  // 建议浏览器在<video>加载元素后是否应该开始下载视频数据。auto浏览器选择最佳行为,立即开始加载视频(如果浏览器支持)
          language: 'zh-CN',
          aspectRatio: '16:9', // 将播放器置于流畅模式,并在计算播放器的动态大小时使用该值。值应该代表一个比例 - 用冒号分隔的两个数字(例如"16:9"或"4:3")
          fluid: true, // 当true时,Video.js player将拥有流体大小。换句话说,它将按比例缩放以适应其容器。
          sources: [{ // 播放资源和资源格式
            type: "video/mp4",
            src: "http://img.ksbbs.com/asset/Mon_1703/05cacb4e02f9d9e.mp4" //你的视频地址(必填)
          }],
          poster: "../static/courses/675076.jpeg", //视频封面图
          width: document.documentElement.clientWidth, // 默认视频全屏时的最大宽度
          notSupportedMessage: '此视频暂无法播放,请稍后再试', //允许覆盖Video.js无法播放媒体源时显示的默认信息。
        }
      }
    },
    methods: {
      // 视频播放事件
      onPlayerPlay(player) {
        alert("play");
      },
      // 视频暂停播放事件
      onPlayerPause(player){
        alert("pause");
      },
      // 视频插件初始化
      player() {
        return this.$refs.videoPlayer.player;
      }
    },
    components:{
      Header,
      Footer,
      videoPlayer,
    }
}
</script>

<style scoped>
.main{
  background: #fff;
  padding-top: 30px;
}
.course-info{
  width: 1200px;
  margin: 0 auto;
  overflow: hidden;
}
.wrap-left{
  float: left;
  width: 690px;
  height: 388px;
  background-color: #000;
}
.wrap-right{
  float: left;
  position: relative;
  height: 388px;
}
.name{
  font-size: 20px;
  color: #333;
  padding: 10px 23px;
  letter-spacing: .45px;
}
.data{
  padding-left: 23px;
  padding-right: 23px;
  padding-bottom: 16px;
  font-size: 14px;
  color: #9b9b9b;
}
.sale-time{
  width: 464px;
  background: #fa6240;
  font-size: 14px;
  color: #4a4a4a;
  padding: 10px 23px;
  overflow: hidden;
}
.sale-type {
  font-size: 16px;
  color: #fff;
  letter-spacing: .36px;
  float: left;
}
.sale-time .expire{
  font-size: 14px;
  color: #fff;
  float: right;
}
.sale-time .expire .second{
  width: 24px;
  display: inline-block;
  background: #fafafa;
  color: #5e5e5e;
  padding: 6px 0;
  text-align: center;
}
.course-price{
  background: #fff;
  font-size: 14px;
  color: #4a4a4a;
  padding: 5px 23px;
}
.discount{
  font-size: 26px;
  color: #fa6240;
  margin-left: 10px;
  display: inline-block;
  margin-bottom: -5px;
}
.original{
  font-size: 14px;
  color: #9b9b9b;
  margin-left: 10px;
  text-decoration: line-through;
}
.buy{
  width: 464px;
  padding: 0px 23px;
  position: absolute;
  left: 0;
  bottom: 20px;
  overflow: hidden;
}
.buy .buy-btn{
  float: left;
}
.buy .buy-now{
  width: 125px;
  height: 40px;
  border: 0;
  background: #ffc210;
  border-radius: 4px;
  color: #fff;
  cursor: pointer;
  margin-right: 15px;
  outline: none;
}
.buy .free{
  width: 125px;
  height: 40px;
  border-radius: 4px;
  cursor: pointer;
  margin-right: 15px;
  background: #fff;
  color: #ffc210;
  border: 1px solid #ffc210;
}
.add-cart{
  float: right;
  font-size: 14px;
  color: #ffc210;
  text-align: center;
  cursor: pointer;
  margin-top: 10px;
}
.add-cart img{
  width: 20px;
  height: 18px;
  margin-right: 7px;
  vertical-align: middle;
}
</style>

8.3完成课程的选项卡内容部分以及讲师信息

<template>
    <div class="detail">
      <Header/>
      <div class="main">
        <div class="course-info">
          <div class="wrap-left">
            <video-player class="video-player vjs-custom-skin"
               ref="videoPlayer"
               :playsinline="true"
               :options="playerOptions"
               @play="onPlayerPlay($event)"
               @pause="onPlayerPause($event)"
            >
            </video-player>
          </div>
          <div class="wrap-right">
            <h3 class="course-name">Linux系统基础5周入门精讲</h3>
            <p class="data">23475人在学&nbsp;&nbsp;&nbsp;&nbsp;课程总时长:148课时/180小时&nbsp;&nbsp;&nbsp;&nbsp;难度:初级</p>
            <div class="sale-time">
              <p class="sale-type">限时免费</p>
              <p class="expire">距离结束:仅剩 01天 04小时 33分 <span class="second">08</span> 秒</p>
            </div>
            <p class="course-price">
              <span>活动价</span>
              <span class="discount">¥0.00</span>
              <span class="original">¥29.00</span>
            </p>
            <div class="buy">
              <div class="buy-btn">
                <button class="buy-now">立即购买</button>
                <button class="free">免费试学</button>
              </div>
              <div class="add-cart"><img src="@/assets/cart-yellow.svg" alt="">加入购物车</div>
            </div>
          </div>
        </div>
        <div class="course-tab">
          <ul class="tab-list">
            <li :class="tabIndex==1?'active':''" @click="tabIndex=1">详情介绍</li>
            <li :class="tabIndex==2?'active':''" @click="tabIndex=2">课程章节 <span :class="tabIndex!=2?'free':''">(试学)</span></li>
            <li :class="tabIndex==3?'active':''" @click="tabIndex=3">用户评论 (42)</li>
            <li :class="tabIndex==4?'active':''" @click="tabIndex=4">常见问题</li>
          </ul>
        </div>
        <div class="course-content">
          <div class="course-tab-list">
            <div class="tab-item" v-if="tabIndex==1">
              <p><img alt="" src="https://hcdn1.luffycity.com/static/frontend/course/12/Linux01_1547102274.4025493.jpeg" width="840"></p>
              <p><img alt="" src="https://hcdn1.luffycity.com/static/frontend/course/12/Linux02_1547102275.9939013.jpeg" width="840"></p>
              <p><img alt="" src="https://hcdn1.luffycity.com/static/frontend/course/12/Linux03_1547102275.730511.jpeg" width="840"></p>
            </div>
            <div class="tab-item" v-if="tabIndex==2">
              <div class="tab-item-title">
                <p class="chapter">课程章节</p>
                <p class="chapter-length">共11章 147个课时</p>
              </div>
              <div class="chapter-item">
                <p class="chapter-title"><img src="@/assets/1.svg" alt="">第1章·Linux硬件基础</p>
                <ul class="lesson-list">
                  <li class="lesson-item">
                    <p class="name"><span class="index">1-1</span> 课程介绍-学习流程<span class="free">免费</span></p>
                    <p class="time">07:30 <img src="@/assets/chapter-player.svg"></p>
                    <button class="try">立即试学</button>
                  </li>
                  <li class="lesson-item">
                    <p class="name"><span class="index">1-2</span> 服务器硬件-详解<span class="free">免费</span></p>
                    <p class="time">07:30 <img src="@/assets/chapter-player.svg"></p>
                    <button class="try">立即试学</button>
                  </li>
                </ul>
              </div>
              <div class="chapter-item">
                <p class="chapter-title"><img src="@/assets/1.svg" alt="">第2章·Linux发展过程</p>
                <ul class="lesson-list">
                  <li class="lesson-item">
                    <p class="name"><span class="index">2-1</span> 操作系统组成-Linux发展过程</p>
                    <p class="time">07:30 <img src="@/assets/chapter-player.svg"></p>
                    <button class="try">立即购买</button>
                  </li>
                  <li class="lesson-item">
                    <p class="name"><span class="index">2-2</span> 自由软件-GNU-GPL核心讲解</p>
                    <p class="time">07:30 <img src="@/assets/chapter-player.svg"></p>
                    <button class="try">立即购买</button>
                  </li>
                </ul>
              </div>
            </div>
            <div class="tab-item" v-if="tabIndex==3">
              用户评论
            </div>
            <div class="tab-item" v-if="tabIndex==4">
              常见问题
            </div>
          </div>
          <div class="course-side">
             <div class="teacher-info">
               <h4 class="side-title"><span>授课老师</span></h4>
               <div class="teacher-content">
                 <div class="cont1">
                   <img src="//hcdn1.luffycity.com/static/frontend/activity/头像@3x_1509542508.019424.png">
                   <div class="name">
                     <p class="teacher-name">李泳谊</p>
                     <p class="teacher-title">老男孩LInux学科带头人</p>
                   </div>
                 </div>
                 <p class="narrative" >Linux运维技术专家,老男孩Linux金牌讲师,讲课风趣幽默、深入浅出、声音洪亮到爆炸</p>
               </div>
             </div>
          </div>
        </div>
      </div>
      <Footer/>
    </div>
</template>

<script>
import Header from "./common/Header"
import Footer from "./common/Footer"

import {videoPlayer} from 'vue-video-player';

export default {
    name: "Detail",
    data(){
      return {
        tabIndex:2, // 当前选项卡显示的下标
        playerOptions: {
          playbackRates: [0.7, 1.0, 1.5, 2.0], // 播放速度
          autoplay: false, //如果true,则自动播放
          muted: false, // 默认情况下将会消除任何音频。
          loop: false, // 循环播放
          preload: 'auto',  // 建议浏览器在<video>加载元素后是否应该开始下载视频数据。auto浏览器选择最佳行为,立即开始加载视频(如果浏览器支持)
          language: 'zh-CN',
          aspectRatio: '16:9', // 将播放器置于流畅模式,并在计算播放器的动态大小时使用该值。值应该代表一个比例 - 用冒号分隔的两个数字(例如"16:9"或"4:3")
          fluid: true, // 当true时,Video.js player将拥有流体大小。换句话说,它将按比例缩放以适应其容器。
          sources: [{ // 播放资源和资源格式
            type: "video/mp4",
            src: "http://img.ksbbs.com/asset/Mon_1703/05cacb4e02f9d9e.mp4" //你的视频地址(必填)
          }],
          poster: "../static/courses/675076.jpeg", //视频封面图
          width: document.documentElement.clientWidth, // 默认视频全屏时的最大宽度
          notSupportedMessage: '此视频暂无法播放,请稍后再试', //允许覆盖Video.js无法播放媒体源时显示的默认信息。
        }
      }
    },
    methods: {
      // 视频播放事件
      onPlayerPlay(player) {
        alert("play");
      },
      // 视频暂停播放事件
      onPlayerPause(player){
        alert("pause");
      },
      // 视频插件初始化
      player() {
        return this.$refs.videoPlayer.player;
      }
    },
    components:{
      Header,
      Footer,
      videoPlayer,
    }
}
</script>

<style scoped>
.main{
  background: #fff;
  padding-top: 30px;
}
.course-info{
  width: 1200px;
  margin: 0 auto;
  overflow: hidden;
}
.wrap-left{
  float: left;
  width: 690px;
  height: 388px;
  background-color: #000;
}
.wrap-right{
  float: left;
  position: relative;
  height: 388px;
}
.course-name{
  font-size: 20px;
  color: #333;
  padding: 10px 23px;
  letter-spacing: .45px;
}
.data{
  padding-left: 23px;
  padding-right: 23px;
  padding-bottom: 16px;
  font-size: 14px;
  color: #9b9b9b;
}
.sale-time{
  width: 464px;
  background: #fa6240;
  font-size: 14px;
  color: #4a4a4a;
  padding: 10px 23px;
  overflow: hidden;
}
.sale-type {
  font-size: 16px;
  color: #fff;
  letter-spacing: .36px;
  float: left;
}
.sale-time .expire{
  font-size: 14px;
  color: #fff;
  float: right;
}
.sale-time .expire .second{
  width: 24px;
  display: inline-block;
  background: #fafafa;
  color: #5e5e5e;
  padding: 6px 0;
  text-align: center;
}
.course-price{
  background: #fff;
  font-size: 14px;
  color: #4a4a4a;
  padding: 5px 23px;
}
.discount{
  font-size: 26px;
  color: #fa6240;
  margin-left: 10px;
  display: inline-block;
  margin-bottom: -5px;
}
.original{
  font-size: 14px;
  color: #9b9b9b;
  margin-left: 10px;
  text-decoration: line-through;
}
.buy{
  width: 464px;
  padding: 0px 23px;
  position: absolute;
  left: 0;
  bottom: 20px;
  overflow: hidden;
}
.buy .buy-btn{
  float: left;
}
.buy .buy-now{
  width: 125px;
  height: 40px;
  border: 0;
  background: #ffc210;
  border-radius: 4px;
  color: #fff;
  cursor: pointer;
  margin-right: 15px;
  outline: none;
}
.buy .free{
  width: 125px;
  height: 40px;
  border-radius: 4px;
  cursor: pointer;
  margin-right: 15px;
  background: #fff;
  color: #ffc210;
  border: 1px solid #ffc210;
}
.add-cart{
  float: right;
  font-size: 14px;
  color: #ffc210;
  text-align: center;
  cursor: pointer;
  margin-top: 10px;
}
.add-cart img{
  width: 20px;
  height: 18px;
  margin-right: 7px;
  vertical-align: middle;
}

.course-tab{
    width: 100%;
    background: #fff;
    margin-bottom: 30px;
    box-shadow: 0 2px 4px 0 #f0f0f0;

}
.course-tab .tab-list{
    width: 1200px;
    margin: auto;
    color: #4a4a4a;
    overflow: hidden;
}
.tab-list li{
    float: left;
    margin-right: 15px;
    padding: 26px 20px 16px;
    font-size: 17px;
    cursor: pointer;
}
.tab-list .active{
    color: #ffc210;
    border-bottom: 2px solid #ffc210;
}
.tab-list .free{
    color: #fb7c55;
}
.course-content{
    width: 1200px;
    margin: 0 auto;
    background: #FAFAFA;
    overflow: hidden;
    padding-bottom: 40px;
}
.course-tab-list{
    width: 880px;
    height: auto;
    padding: 20px;
    background: #fff;
    float: left;
    box-sizing: border-box;
    overflow: hidden;
    position: relative;
    box-shadow: 0 2px 4px 0 #f0f0f0;
}
.tab-item{
    width: 880px;
    background: #fff;
    padding-bottom: 20px;
    box-shadow: 0 2px 4px 0 #f0f0f0;
}
.tab-item-title{
    justify-content: space-between;
    padding: 25px 20px 11px;
    border-radius: 4px;
    margin-bottom: 20px;
    border-bottom: 1px solid #333;
    border-bottom-color: rgba(51,51,51,.05);
    overflow: hidden;
}
.chapter{
    font-size: 17px;
    color: #4a4a4a;
    float: left;
}
.chapter-length{
    float: right;
    font-size: 14px;
    color: #9b9b9b;
    letter-spacing: .19px;
}
.chapter-title{
    font-size: 16px;
    color: #4a4a4a;
    letter-spacing: .26px;
    padding: 12px;
    background: #eee;
    border-radius: 2px;
    display: -ms-flexbox;
    display: flex;
    -ms-flex-align: center;
    align-items: center;
}
.chapter-title img{
    width: 18px;
    height: 18px;
    margin-right: 7px;
    vertical-align: middle;
}
.lesson-list{
    padding:0 20px;
}
.lesson-list .lesson-item{
    padding: 15px 20px 15px 36px;
    cursor: pointer;
    justify-content: space-between;
    position: relative;
    overflow: hidden;
}
.lesson-item .name{
    font-size: 14px;
    color: #666;
    float: left;
}
.lesson-item .index{
    margin-right: 5px;
}
.lesson-item .free{
    font-size: 12px;
    color: #fff;
    letter-spacing: .19px;
    background: #ffc210;
    border-radius: 100px;
    padding: 1px 9px;
    margin-left: 10px;
}
.lesson-item .time{
    font-size: 14px;
    color: #666;
    letter-spacing: .23px;
    opacity: 1;
    transition: all .15s ease-in-out;
    float: right;
}
.lesson-item .time img{
    width: 18px;
    height: 18px;
    margin-left: 15px;
    vertical-align: text-bottom;
}
.lesson-item .try{
    width: 86px;
    height: 28px;
    background: #ffc210;
    border-radius: 4px;
    font-size: 14px;
    color: #fff;
    position: absolute;
    right: 20px;
    top: 10px;
    opacity: 0;
    transition: all .2s ease-in-out;
    cursor: pointer;
    outline: none;
    border: none;
}
.lesson-item:hover{
    background: #fcf7ef;
    box-shadow: 0 0 0 0 #f3f3f3;
}
.lesson-item:hover .name{
    color: #333;
}
.lesson-item:hover .try{
    opacity: 1;
}

.course-side{
    width: 300px;
    height: auto;
    margin-left: 20px;
    float: right;
}
.teacher-info{
    background: #fff;
    margin-bottom: 20px;
    box-shadow: 0 2px 4px 0 #f0f0f0;
}
.side-title{
    font-weight: normal;
    font-size: 17px;
    color: #4a4a4a;
    padding: 18px 14px;
    border-bottom: 1px solid #333;
    border-bottom-color: rgba(51,51,51,.05);
}
.side-title span{
    display: inline-block;
    border-left: 2px solid #ffc210;
    padding-left: 12px;
}

.teacher-content{
    padding: 30px 20px;
    box-sizing: border-box;
}

.teacher-content .cont1{
    margin-bottom: 12px;
    overflow: hidden;
}

.teacher-content .cont1 img{
    width: 54px;
    height: 54px;
    margin-right: 12px;
    float: left;
}
.teacher-content .cont1 .name{
    float: right;
}
.teacher-content .cont1 .teacher-name{
    width: 188px;
    font-size: 16px;
    color: #4a4a4a;
    padding-bottom: 4px;
}
.teacher-content .cont1 .teacher-title{
    width: 188px;
    font-size: 13px;
    color: #9b9b9b;
    white-space: nowrap;
}
.teacher-content .narrative{
    font-size: 14px;
    color: #666;
    line-height: 24px;
}
</style>

效果:

1556538277772

推荐阅读