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>

如今看下頁面,是否是已經出來了呢?

相關文章
相關標籤/搜索