Vue-cli-webpack-从零开始的斗鱼直播(一)

前言

想必你们都看过斗鱼直播吧?此次在下使用从github上面摸下来的API,为你们重现一下斗鱼网站的搭建,使用vue-cli-webpack来实现。
文章内容较多,能够慢慢看css

声明

本文章所用API均从网络获取,本文做者不承担任何法律责任,请阅读本文的小伙伴们用于学习用途,不能用于商业!
若有侵权行为,请与做者联系,做者将于2日内删除。html

开始以前

本文假设您学习了如下相关知识
nodejs
webpack
vue
vue-cli
vue-routervue

效果

pc端node

图片描述

移动端webpack

图片描述

开始

好,扯了这么久的淡,该开始构建项目了ios

项目初始化

初始化文件夹

打开一个新文件夹,在命令行输入:git

vue init webpack

若是显示vue not found,那么该去下载vue-cli,若是webpack未找到就去下载webpackgithub

一路回车便可,遇到Y就选y,而后回车

到这一步之后就ctrl + c ,退出终端web

安装依赖

退出命令行以后,输入如下指令:vue-router

npm install chromedriver --chromedriver_cdnurl=http://cdn.npm.taobao.org/dist/chromedriver

chromedriver 是安装必备的包,镜像好像有问题,咱们提早装一下。

npm install

GFW不是吹的,外网真的很慢,你们泡杯茶慢慢等
趁着等的时候,咱们来下载几个样式和图片,运行

git clone https://github.com/YexChen/douyu_assets.git

来下载assets文件,覆盖 assets文件夹到 项目文件/src 中

npm i -S lib-flexible
npm i -S axios
npm i -S vue-axios

咱们还须要lib-flexible来解决移动端适配的问题,axios和vue-axios来方便请求咱们的数据

引入安装的包

你们能够进入到src目录下,这里简要介绍下各个文件的功能

assets    放静态内容的地方,可是支持预编译
components    放组件的地方,固然也能够别具一格随便创个文件夹代替之
router/index.js  router文件夹是放路由的地方,index.js是咱们的根路由   
app.vue    vue-cli帮咱们生成好的一个组件(根组件),没什么好稀奇的
main.js    webpack的入口文件,聚合vue应用里面的东西

咱们来修改main.js,参照下图:
图片描述

红线区域咱们引入了移动适配的lib-flexible,和font-awesome,style公共样式

接下来,咱们来引入axios和vue-axios,请看下图:
图片描述

这里咱们引入了vue-axios和axios,并经过vue.use来进行绑定

跑起项目

准备工做已经作完了,接下来能够跑起项目了:

npm run dev

根据命令行的提示打开网页便可看到效果:
图片描述

好的,咱们的项目初始化就到这里了。

配置映射和测试斗鱼API

配置映射

来到根目录下的 config/index.js 这里是配置开发,构建,及路由映射的地方
图片描述

如图修改proxyTable中内容,这里解释一下几个参数:

target : 目标地址,
changeOrigin : 是否跨域,
pathRewrite : 键值对中用值替换键的值,其中^是正则中表示开始的符号

随手请求一个API

进入src/App.vue,以下修改文件:
图片描述

created是咱们的生命钩子函数,vue实例在created阶段会执行里面的代码。
this.$http至关于this.axios,$http的具体实现能够去node_modules里面看,很简单的

重启webpack服务,看下效果

ctrl+c
npm run dev

图片描述
看到以上效果的话,证实数据请求成功了。

思惟导图解析

咱们要写的应用较为复杂,写vue的项目就是这样,须要清晰的思想,否则很容易崩溃,最后重来
图片描述

好,接下来为你们讲解一下咱们的组件:
Root是根组件,一切的源(废话)

App,应用组件,对应src/App.vue
    Side-menu :侧边栏,由于较为容易且不须要改变单页路由来显示不一样内容,因此直接放在app组件里边
    router-view : 这是vue-router的子路由显示面板,经过src/router/index.js来控制
    home : 主页视图文件
    public : 公用组件,亦可在其余页面使用,下降工做量
    AppHeader : 应用头部组件
    Loading : 加载中的组件,就一张gif

侧边栏SideMenu组件

在src/components目录中新建一个文件,名为SideMenu.vue,修改内容为:

<template lang="html">
  <div class="side-menu" @click = "hideSide">
    <ul>
      <router-link v-for = "(item,index) in list" :to="item.url" :key = "index">
        {{item.title}}
        <i class = "icon-chevron-right"></i>
      </router-link>
    </ul>
  </div>
</template>

<script>
export default {
  data(){
    return {
      list : [
        {title : "首页",url : "/"},
        {title : "所有分类",url : "/category"}
      ]
    }
  },
  methods : {
    hideSide(){
      this.$emit("hide")
    }
  }
}
</script>

<style lang="css">
  .side-menu {
    background: rgba(10,10,10,.3);
    height: 100%;
    position: fixed;
    width: 100%;
    top: 0;
    padding-top: 44px;
    z-index: 11;
  }
  .side-menu ul {
    width: 70%;
    background: #282828;
    height: 100%;
    border-top: 1px solid #222;
  }
  .side-menu ul li {
    height: 50px;
    border-bottom: 1px dotted #333;
    font-size: 14px;
    line-height: 50px;
    padding: 0 30px 0 20px;
    color: #9a9a9a;
  }
  .side-menu ul li i {
    float: right;
    line-height: 50px;
  }
</style>

这里解释一下文件里面的内容:
文件分为三大块

template
script
style

这些内容经过script中node的export方法推出去
其中template渲染了几个router-link,用来跳转路由
script定义了data和method
style写了样式

而后打开src/App.vue,修改里面的内容,追加下图内容:
图片描述

好的,咱们的SideMenu组件就注册完成了。

搭建router-view内容

好的,咱们接下来作router-view的内容

bus-中央总线

在作以前,咱们须要了解一个新的概念-bus,又称中央总线
图片描述

好的,又是以前那张思惟导图,不过是否是多出了三台车呢?
没错,这就是咱们的bus。
当appheader想加载侧边栏时,是不能穿越徒步穿越山和大海的,老司机仍是要开车的是否是
这个时候咱们坐公交就好了,告诉app,把我给拉出来
固然,side-menu和app之间相距不远,父子组件是能够直接绑定的

在src目录下建立bus.js,内容为
图片描述

这是咱们的bus,说白了就是一个对象,只不过借用了vue的消息管道,你们也能够本身写个管道

制造home主页路由

在src目录下建立pages目录,这个目录咱们用来存放router-vue的内容
而后咱们在src/pages/下建立一个home.vue组件,用来作home的内容,写下如下内容:

<template lang="html">
  <div class="mr-root">
    <app-header>
      <p class = "title">斗鱼TV</p>
    </app-header>
    <loading v-if="showLoading"></loading>
  </div>
</template>

<script>
import Public from "../public"
export default {
  mixins : [
    Public
  ],
  data(){
    return {
      showLoading : true
    }
  }
}
</script>

<style lang="css" scoped>
</style>

解释一下,这里使用了app-header和loading组件,由Public导入(等会写)。
mixins是一个混合物,可以自动把模组分析,加载到当前实例中。
data中 showLoading和v-if配合使用,用来关闭loading效果
若是不清楚的话能够看下思惟导图

public公用模组

public是一个模组集合,咱们在开发的时候可能不一样页面要使用相同的组件,这时就须要public打包处理了。
在src中新建public.js,内容以下:

import AppHeader from './components/AppHeader'
import Loading from './components/Loading'

export default{
  components: {
    AppHeader,
    Loading
  }
}

上文咱们导入了AppHeader和Loading模块,并设置了默认导出

好,那么咱们来写两个子模组,

AppHeader

在components中新建一个文件AppHeader.vue,代码以下

<template lang="html">
  <header>
    <i class = "icon-reorder" @click = "showSlide"></i>
    <slot></slot>
    <i class = "icon-user"></i>
  </header>
</template>

<script>
import bus from "../bus"
export default {
  methods : {
    showSlide(){
      bus.$emit('showSide')
    }
  }
}
</script>

<style lang="css" scoped>
  header {
    height: 44px;
    background: #333;
    position: fixed;
    left: 0;
    right: 0;
    top: 0;
    z-index: 100;
    padding: 0 15px;
    color: #fff;
    line-height: 44px;
    font-size: 16px;
  }
  header i {
    color: #999;
  }

  .title {
    margin-left: 15px;
    display: inline-block;
  }

  .icon-user {
    float: right;
    line-height: 44px;
  }
</style>

定义了基本的头部,给加载更多绑定了一个事件,经过bus进行传递,由app.vue来实现

Loading组件

src/components/里面新建一个Loading.vue,代码以下:

<style lang="css">
  .loading {
    height: 100%;
    position: fixed;
    z-index: 10;
    width: 100%;
    background: #062734;
    opacity: .4;
  }

  .loading img {
    width: 100%;
    height: auto;
    position: absolute;
    top: calc(50% - 140px);
  }
</style>

就添加了一张gif图而已,很是简单的

bus事件的处理

好的,既然咱们的appheader已经发车了,那么应该在app.vue根路由里面开个公交车站,来接收巴士:
修改App.vue:

<template>
  <div id="app">
    <transition name = "side">
      <side-menu v-show = "show" @hide = "hideSide"></side-menu>
    </transition>
    <router-view/>
  </div>
</template>

<script>
import SideMenu from "./components/SideMenu"
import bus from "./bus"
export default {
  name: 'app',
  components : {
    SideMenu
  },
  created(){
    this.$http.get(`/douyuapi/RoomApi/live?offset=1&limit=20`).then(res=>{
      console.log(res.data.data);
    })
  },
  data(){
    return {
      show : false
    }
  },
  mounted () {
    bus.$on("showSide",this.side)
  },
  methods : {
    side(){
      this.show = !this.show
    },
    hideSide(){
      this.show = false
    }
  }
}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

修改路由

修改根路由/src/router/index.js为:

import Vue from 'vue'
import Router from 'vue-router'
import Home from '@/pages/Home'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'Home',
      component: Home
    }
  ]
})

增长HomeItem

好的,咱们有了以上功能之后呢,还须要在斗鱼主页中增长聊天室列表,在components目录中新建文件HomeItem.vue

<template lang="html">
  <div class="mr-item">
    <router-link :to="'/room/'+room.room_id">
      <img :src="room.room_src" alt="">
      <div class="room-info">
        <span class = "nickname">{{room.nickname}}</span>
        <span class = "count">
          <i class = "icon-group"></i>
          {{room.online | number}}
        </span>
      </div>
      <div class="room-title">
        <i class = "icon-desktop"></i>
        {{room.room_name | message}}
      </div>
    </router-link>
  </div>
</template>

<script>
export default {
  props : ["room"]
}
</script>

<style lang="css" scoped>
  .mr-item {
    margin-top: 10px;
    float: left;
    width: 4.4rem;
    margin-right: .3rem;
    position: relative;
  }

  .mr-item img {
    width: 100%;
    height: 2.6rem;
    border-radius: 5px;
  }

  .room-info {
    position: absolute;
    bottom: 33px;
    color: #fff;
    padding: 0 5px;
    left: 0;
    right: 0;
    overflow: hidden;
    background: rgba(10,10,10,.5);
    line-height: 24px;
    border-bottom-left-radius: 5px;
    border-bottom-right-radius: 5px;
  }

  .room-info .count {
    float: right;
  }

  .room-title {
    line-height: 30px;
  }

</style>

上文中咱们定义了两个过滤器,接下来咱们在main.js中定义几个过滤器

main.js定义过滤器

打开main.js,在Vue.config.productionTip = false后,如图写下过滤器代码
图片描述

home.vue中加载homeitem

咱们须要在Home.vue中加载HomeItem,修改home.vue为

<template lang="html">
  <div class="mr-root">
    <app-header>
      <p class = "title">斗鱼TV</p>
    </app-header>
    <loading v-if="showLoading"></loading>
    <home-item v-for = "(room,index) in roomList" :room = "room" :key = "index">
    </home-item>
    <p v-if = "error">加载失败,请稍后再试...</p>
    <div class="clear"></div>
    <div class="load-more">
      <span @click = "loadMore">点击加载更多</span>
    </div>
  </div>
</template>

<script>
import Public from "../public"
import HomeItem from "../components/HomeItem"
export default {
  mixins : [
    Public
  ],
  data(){
    return {
      showLoading : true,
      error : false,
      roomList : [],
      page : 0,
      pageSize : 20
    }
  },
  components : {
    HomeItem
  },
  created(){
    this.getInfo(this.page)
  },
  methods : {
    getInfo(page){
      this.$http.get(`/douyuapi/RoomApi/live?offset=${page*this.pageSize}&limit=${this.pageSize}`)
      .then(res=>{
        this.error = false
        this.roomList = this.roomList.concat(res.data.data)
        setTimeout(()=>{
          this.showLoading = false
        },1000)
      })
      .catch(err=>{
        this.error = true
        this.showLoading = false
      })
    },
    loadMore(){
      this.page++
      this.getInfo(this.page)
    }
  }
}
</script>

<style lang="css">
.mr-content {
  padding: 44px 0 0 .3rem;
  overflow: hidden;
}
.load-more {
  margin: 10px;
  text-align: center;
}
.load-more span {
  display: inline-block;
  line-height: 30px;
  padding: 0 20px;
  border-radius: 10px;
  border: 1px solid #000;
}
</style>

如今看下页面,是否是已经出来了呢?

相关文章
相关标签/搜索