前端Vue項目——首頁/課程頁面開發及Axios請求

1、首頁輪播圖

一、elementUI走馬燈

  elementUI中 Carousel 走馬燈,能夠在有限空間內,循環播放同一類型的圖片、文字等內容。css

  這裏使用指示器樣式,能夠將指示器的顯示位置設置在容器外部:vue

<template>
  <el-carousel indicator-position="outside">
    <el-carousel-item v-for="item in 4" :key="item">
      <h3>{{ item }}</h3>
    </el-carousel-item>
  </el-carousel>
</template>

  indicator-position 屬性定義了指示器的位置。默認狀況下,會顯示在走馬燈內部,設置爲 outside 則會顯示在外部;設置爲 none 則不會顯示指示器。node

二、首頁引入指示器樣式

  編寫 src/components/Home/Home.vue 文件以下所示:ios

<template>
  <el-carousel indicator-position="outside" height="600px">
    <el-carousel-item v-for="item in lunboImgs" :key="item.id">
      <img :src="item.imgSrc" alt="">
    </el-carousel-item>
  </el-carousel>
</template>

<script>
  export default {
    name: "Home",
    data() {
      return {
        lunboImgs: [
          {
            id: 1,
            imgSrc: 'https://hcdn1.luffycity.com/static/frontend/index/banner1(4)_1539945492.0492468.png'
          },
          {
            id:2,
            imgSrc:'https://hcdn1.luffycity.com/static/frontend/index/騎士(1)_1539945488.713867.png'
          },
          {
            id:3,
            imgSrc:'https://hcdn1.luffycity.com/static/frontend/index/banner11_1538122470.2779157.png'
          },
          {
            id:4,
            imgSrc:'https://hcdn1.luffycity.com/static/frontend/index/home-banner4_1535545832.4715614.png'
          }
        ]
      };
    },
    created() {
      console.log(localStorage);
    }
  };
</script>

<style lang="css" scoped>
img{
  width: 100%;
  height: 100%;
}
</style>

  顯示效果以下所示:ajax

  

2、免費課程頁面

一、引入和使用Axios

  因爲須要使用Ajax發送請求,所以須要引入Axios。npm

  Axios 是一個基於 promise 的 HTTP 庫,能夠用在瀏覽器和 node.js 中。首先下載Axios:element-ui

$ npm install axios -S

  安裝其餘插件的時候,能夠直接在 main.js 中引入並 Vue.use(),可是 axios 不能use ,只能在每一個須要發送請求的組件中即時引入json

二、在main.js中引入axios

  要解決要在每一個組件即時引入 axios 的問題,有兩種開發思路:一是須要在引入 axios後修改原型鏈;二是結合Vuex,封裝一個actionaxios

  這裏使用引入axios後修改原型鏈的方法,在 main.js 中導入和掛載 Axios 到原型實例上:api

import Vue from 'vue'
import App from './App'
import router from './router'
// elementUI導入
import ElementUI from 'element-ui'
// 注意樣式文件須要單獨引入
import 'element-ui/lib/theme-chalk/index.css'
import '../static/global/global.css'
// 導入axios
import Axios from 'axios'
Vue.prototype.$http = Axios;  // 掛載在原型上,後面能夠在任意組件使用
Axios.defaults.baseURL = 'https://www.luffycity.com/api/v1/';   // 設置公共url

// 調用插件
Vue.use(ElementUI);

Vue.config.productionTip = false;

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

  在main.js中添加這兩行紅色代碼後,就能直接在組件的 methods 中使用 $http 命令了。

三、免費課程列表實現

  編寫 src/components/Course/Course.vue 文件以下所示:

<template>
  <div class="course">
    <div class="container clearfix">
      <!-- 課程分類 -->
      <ul class="coursebox">
        <li v-for="(category,index) in categoryList" :key="category.id">
          {{category.name}}
        </li>
        <li>
          Python
        </li>
      </ul>
      <div class="courseList">
        <div class="detail">
          <div class="head">
            <img src="" alt="" class="backImg">
            <b class="mask"></b>
            <p>Python開發21天入門</p>
          </div>
          <div class="content">
            <p>Python以其簡潔、優雅、高效的特色,稱爲目前最流行的4大主流開發語言</p>
            <div class="content-detail">
              <div>
                <img src="data:image/svg+xml;base64,PD9...4K" alt="">
                <span>1836</span>
                <span>初級</span>
                <span class="span3">
                  <span class="s">¥99.0</span>
                  <span  class="t">免費</span>
                </span>
                <span class="span4"></span>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
  export default {
    name: "Course",
    data() {
      return {
        categoryList: [], // 課程分類列表
      };
    },
    // 生命週期 在created方法發起ajax請求
    created () {
      console.log(this.$http);   // Axios對象
      this.$http.get('course_sub/category/list/')    // 發送get請求
        .then(res=>{   // 請求以後對應的結果
          console.log(res);
          console.log(res.data.data);   // 獲取列表中數組
          if (!res.data.error_no) {
            this.categoryList = res.data.data;
          }
        })
        .catch(err=>{
          console.log(err);
        })
    }
  };
</script>

(1)課程列表顯示效果

  樣式略,顯示效果以下所示:

  

(2)在created方法發送get請求

// 生命週期 在created方法發起ajax請求
created () {
  console.log(this.$http);   // Axios對象
  this.$http.get('course_sub/category/list/')    // 發送get請求
  .then(res=>{   // 請求以後對應的結果
    console.log(res);
    console.log(res.data.data);   // 獲取列表中數組
    if (!res.data.error_no) {
      this.categoryList = res.data.data;
    }
  })
  .catch(err=>{
    console.log(err);
  })
}

  完整的請求應包括 .then.catch。當請求成功時,會執行 .then,不然執行 .catch。

四、axios模塊封裝

   在vue項目中,與後臺交互獲取數據一般是使用的 axios 庫。使用axios發起一個請求是比較簡單的事,可是若是axios沒有進行封裝複用,項目愈來愈大時,會引發代碼冗餘 ,使代碼變得難以維護。所以須要對 axios 進行二次封裝,使項目中各個組件可以複用請求,讓代碼更加容易維護。

(1)封裝要點 

  • 統一 url 配置;
  • 統一 api 請求;
  • request(請求)攔截器,例如:帶上token等,設置請求頭
  • response(響應)攔截器,例如:統一錯誤處理,頁面重定向等
  • 根據需求,結合Vuex作全局的loading動畫或錯誤處理
  • 將axios封裝成Vue插件使用

 (2)axios組件準備

  在項目的src目錄中,新建 restful 文件夾,在這裏是建立  api.js 文件來封裝axios。

// src/restful/api.js
// 導入axios
import Axios from 'axios'

Axios.defaults.baseURL = 'https://www.luffycity.com/api/v1/';   // 設置公共url

// 分類列表 api
// export const categoryList = function function_name(argument) {
export const categoryList = () => {   // 匿名函數改成箭頭函數
  return Axios.get('course_sub/category/list/').then(res=>{
    return res.data;   // 能夠簡寫爲.then(res=>res.data);
  })
};

(3)修改main.js文件引入api.js

import Vue from 'vue'
import App from './App'
import router from './router'
// elementUI導入
import ElementUI from 'element-ui'
// 注意樣式文件須要單獨引入
import 'element-ui/lib/theme-chalk/index.css'
import '../static/global/global.css'

// 調用插件
Vue.use(ElementUI);

import * as api from './restful/api'
console.log(api);
Vue.prototype.$http = api;   // 能夠在各個組件中使用this.$http方法

Vue.config.productionTip = false;

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

  JavaScript 對象都會從一個 prototype(原型對象)中繼承屬性和方法,綁定給原型對象後,就能夠在各個組件中使用this.$http方法了。

(4)Course組件使用新封裝的axios

  在Couse.vue中,能夠經過this.$http獲取 Axios對象,使用封裝好的接口來發送get請求。

<script>
  export default {
    name: "Course",
    data() {
      return {
        categoryList: [], // 課程分類列表
      };
    },
    // 生命週期 在created方法發起ajax請求
    created () {
      console.log(this.$http);   // Axios對象
      // this.$http.get('course_sub/category/list/')    // 發送get請求
      this.$http.categoryList()
      .then(res=>{   // 請求以後對應的結果
        console.log(res);
        if (!res.error_no) {
          this.categoryList = res.data;
        }
      })
      .catch(err=>{
        console.log(err);
      })
    }
  };
</script>

五、分類列表實現

  在Couse.vue中,添加課程分類對象到課程分類列表中:

<script>
  export default {
    name: "Course",
    data() {
      return {
        categoryList: [], // 課程分類列表
      };
    },
    // 生命週期 在created方法發起ajax請求
    created () {
      console.log(this.$http);   // Axios對象
      // this.$http.get('course_sub/category/list/')    // 發送get請求
      this.$http.categoryList()
      .then(res=>{   // 請求以後對應的結果
        console.log(res);
        if (!res.error_no) {
          this.categoryList = res.data;
          let category = {   // 課程分類對象
            id: 0,
            category: 0,
            name: "所有"
          };
          this.categoryList.unshift(category);   // unshift() 方法可向數組的開頭添加一個或更多元素,並返回新的長度
        }
      })
      .catch(err=>{
        console.log(err);
      })
    }
  };
</script>

(1)Javascript unshift()方法

  unshift() 方法可向數組的開頭添加一個或更多元素,並返回新的長度。返回值:數組對象的新長度。

  若是要把一個或多個元素添加到數組的尾部,需使用 push() 方法。

  unshift() 方法將把它的參數插入 arrayObject 的頭部,並將已經存在的元素順次地移到較高的下標處,以便留出空間。該方法的第一個參數將成爲數組的新元素 0,若是還有第二個參數,它將成爲新的元素 1,以此類推。

  請注意,unshift() 方法不建立新的建立,而是直接修改原有的數組。

(2)顯示效果以下所示

  

六、分類列表樣式

  對給激活的列表樣式設置特殊樣式,並實現分類列表點擊跳轉:

(1)設置激活中的分類列表樣式

  這裏使用 v-bind 綁定 class,類名 active 依賴於 "index===currentIndex" 的判斷結果。

<template>
  <div class="course">
    <div class="container clearfix">
      <!-- 課程分類 -->
      <ul class="coursebox">
        <li v-for="(category,index) in categoryList" :key="category.id"
          :class="{active:index===currentIndex}">
          {{category.name}}
        </li>
      </ul>
      <!-- 代碼省略 -->
    </div>
  </div>
</template>

<script>
  export default {
    name: "Course",
    data() {
      return {
        categoryList: [], // 課程分類列表
        currentIndex: 0   // 分類列表選中
      };
    },
    // 代碼省略
  };
</script>

<style lang="css" scoped>
  ul li{
    float: left;
    margin-right: 24px;
    cursor: pointer;
  }
  ul li.active{
    color: #00b4e4;
  }
</style>

  顯示效果:

  

(2)分類列表點擊樣式切換

  在課程分類的li 標籤中綁定點擊事件,並編寫方法處理點擊事件:

<template>
  <div class="course">
    <div class="container clearfix">
      <!-- 課程分類 -->
      <ul class="coursebox">
        <li v-for="(category,index) in categoryList" :key="category.id"
          :class="{active:index===currentIndex}" @click="categoryClick(index)">
          {{category.name}}
        </li>
      </ul>
      <!-- 代碼省略 -->
    </div>
  </div>
</template>

<script>
  export default {
    name: "Course",
    data() {
      return {
        categoryList: [], // 課程分類列表
        currentIndex: 0   // 分類列表選中
      };
    },
    methods: {
      categoryClick(index) {
        this.currentIndex = index;    // 修改分類列表的樣式
      }
    },
    // 生命週期 在created方法發起ajax請求
    created () {
      // 代碼省略
    }
  };
</script>

  顯示效果:

  

3、免費課程——所有課程實現

一、準備所有課程API

  將 src/restful/api.js 文件修改以下:

// 導入axios
import Axios from 'axios'

Axios.defaults.baseURL = 'https://www.luffycity.com/api/v1/';   // 設置公共url

// 分類列表 api
// export const categoryList = function function_name(argument) {
export const categoryList = () => {   // 匿名函數改成箭頭函數
  return Axios.get('course_sub/category/list/').then(res=>{
    return res.data;   // 能夠簡寫爲.then(res=>res.data);
  })
};

export const allCategoryList = (categoryId) => {
  return Axios.get(`courses/?sub_category=${categoryId}`).then(res=>res.data);
};

  ES6中提供了模版字符串`(反引號)標識,用${}將變量括起來。這樣能夠簡化操做,不須要再使用大量的""和+來拼接字符串和變量。

二、get請求獲取所有課程信息

  改寫Course.vue組件,使用 created 鉤子調用 methods 中的方法來實現axios請求發送。

<script>
  export default {
    name: "Course",
    data() {
      return {
        categoryList: [], // 課程分類列表
        currentIndex: 0,  // 分類列表選中
        categoryId: 0,    // 獲取全部的課程列表的id
      };
    },
    methods: {
      categoryClick(index) {
        this.currentIndex = index;    // 修改分類列表的樣式
      },
      // 獲取分類列表
      getCategoryList() {
        // this.$http.get('course_sub/category/list/')    // 發送get請求
        this.$http.categoryList()
          .then(res=>{   // 請求以後對應的結果
            console.log(res);
            if (!res.error_no) {
              this.categoryList = res.data;
              let category = {   // 課程分類對象
                id: 0,
                category: 0,
                name: "所有"
              };
              this.categoryList.unshift(category);   // unshift() 方法可向數組的開頭添加一個或更多元素,並返回新的長度
            }
          })
          .catch(err=>{
            console.log(err);
          })
      },
      // 獲取所有的課程列表
 getAllCategoryList() {
        this.$http.allCategoryList(this.categoryId)
          .then(res=>{
            console.log(res);
          })
          .catch(err=>{
            console.log(err);
          })
      }
    },
    // 生命週期 在created方法發起ajax請求
    created () {
      // console.log(this.$http);   // Axios對象
      this.getCategoryList();
      this.getAllCategoryList();
    }
  };
</script>

  在console中查看請求返回的數據:

  

三、 所有課程列表詳情數據

  在獲取所有課程列表時,能夠看到返回的json中包含data: Array(23),這是一個數組,數組中有一個個課程對象,包含課程詳情數據。

<script>
  export default {
    name: "Course",
    data() {
      return {
        categoryList: [], // 課程分類列表
        currentIndex: 0,  // 分類列表選中
        categoryId: 0,    // 獲取全部的課程列表的id
        courseDetail: []  // 課程列表詳情數據
      };
    },
    methods: {
      categoryClick(index) {
        this.currentIndex = index;    // 修改分類列表的樣式
      },
      // 獲取分類列表
      getCategoryList() {
        // 代碼省略
      },
      // 獲取所有的課程列表
      getAllCategoryList() {
        this.$http.allCategoryList(this.categoryId)
          .then(res=>{
            console.log(res);
            if (!res.error_no) {   // 若是沒有錯誤
              this.courseDetail = res.data;
            }
          })
          .catch(err=>{
            console.log(err);
          })
      }
    },
    // 生命週期 在created方法發起ajax請求
    created () {
      // console.log(this.$http);   // Axios對象
      this.getCategoryList();
      this.getAllCategoryList();
    }
  };
</script>

  將返回結果中的data數組賦給 this.courseDetail。

四、所有課程中數據渲染

  v-for 循環data 數組,獲取其中的課程對象,經過模板語法綁到頁面中。

<template>
  <div class="course">
    <div class="container clearfix">
      <!-- 課程分類 -->
      <ul class="coursebox">
        <li v-for="(category,index) in categoryList" :key="category.id"
          :class="{active:index===currentIndex}" @click="categoryClick(index)">
          {{category.name}}
        </li>
      </ul>
      <div class="courseList">
        <div class="detail" v-for="(course, index) in courseDetail" :key="course.id">
          <div class="head">
            <img src="" alt="" class="backImg">
            <b class="mask"></b>
            <p>{{ course.name }}</p>
          </div>
          <div class="content">
            <p>{{ course.teacher_description }}</p>
            <div class="content-detail">
              <div>
                <img src="data:image/svg+xml;base64,PD...Zz4K" alt="">
                <span>{{course.learn_number}}</span>
                <span class="span3" v-if="course.promotion_price">
                  <span class="s">¥{{course.promotion_price}}</span>
                  <span  class="t">{{course.promotion_name}}</span>
                </span>
                <span class="span4" v-else>¥{{course.price}}</span>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

  綁定數據後顯示效果以下所示:

  

五、課程背景色變化渲染

  使用 forEach 方法調用數組每一個元素,並將元素傳遞給回調函數。注意:forEach() 對於空數組是不會執行回調函數的。

  基於 forEach 方法來實現背景色變化渲染:

<template>
  <div class="course">
    <div class="container clearfix">
      <!-- 課程分類 -->
      <ul class="coursebox">
        <li v-for="(category,index) in categoryList" :key="category.id"
          :class="{active:index===currentIndex}" @click="categoryClick(index)">
          {{category.name}}
        </li>
      </ul>
      <div class="courseList">
        <div class="detail" v-for="(course, index) in courseDetail" :key="course.id">
          <div class="head">
            <img :src="course.course_img" alt="" class="backImg">
            <!-- 背景色:行內樣式優先顯示 -->
            <b class="mask" :style="{background: course.bgColor}"></b>
            <p>{{ course.name }}</p>
          </div>
          <!-- 代碼省略-->
      </div>
    </div>
  </div>
</template>

<script>
  export default {
    name: "Course",
    data() {
      return {
        categoryList: [], // 課程分類列表
        currentIndex: 0,  // 分類列表選中
        categoryId: 0,    // 獲取全部的課程列表的id
        courseDetail: [],  // 課程列表詳情數據
        bgColors: ['#4AB2BF','#1895C6','#4C87E0','#A361D9','#F7AE6A','#FF14A0', '#61F0E1',
          '#6282A7','#27998E','#3C74CC','#A463DA','#F0A257','#DD4B7A', '#59C6BD','#617FA1',
          '#1B92C3','#30A297','#3B73CB','#9E57CA','#A463DA','#1895C6','#A361D9','#FF14A0']
      };
    },
    methods: {
      // 代碼省略
      // 獲取所有的課程列表
      getAllCategoryList() {
        this.$http.allCategoryList(this.categoryId)
          .then(res=>{
            console.log(res);
            if (!res.error_no) {   // 若是沒有錯誤
              this.courseDetail = res.data;
              // 添加背景色
              this.courseDetail.forEach((item, index)=>{   // 遍歷數組中對象
                this.bgColors.forEach((bgColor, i)=>{      // 遍歷數組中顏色
                  if (i===index) {
                    item.bgColor = bgColor
                  }
                })
              });
              console.log(this.courseDetail);
            }
          })
          .catch(err=>{
            console.log(err);
          })
      }
    },
    // 生命週期 在created方法發起ajax請求
    created () {
      // console.log(this.$http);   // Axios對象
      this.getCategoryList();
      this.getAllCategoryList();
    }
  };
</script>

  給背景色綁定爲行內樣式,優先顯示。同時綁定上背景圖片,優化顯示效果,效果以下所示:

  

4、分類列表切換課程

  在categoryId=0時,調用getAllCategoryList方法時,默認獲取全部課程列表的數據。

  要實現分類列表切換,顯示對應課程信息,須要在點擊事件中添加對應課程分類的categoryId信息。

一、修改分類列表點擊事件傳參

<template>
  <div class="course">
    <div class="container clearfix">
      <!-- 課程分類 -->
      <ul class="coursebox">
        <li v-for="(category,index) in categoryList" :key="category.id"
          :class="{active:index===currentIndex}" @click="categoryClick(index, category.id)">
          {{category.name}}
        </li>
      </ul>
      <!-- 代碼略 -->
</template>

  在點擊事件中除了傳遞index外,還傳遞了category.id信息。

二、修改分類列表點擊事件

  categoryClick事件點擊觸發後,除了獲取到對應的傳參外,還應執行getAllCategoryList函數,獲取對應分類的全部課程。

  須要注意,getAllCategoryList() 方法中的 this.categoryId 已經修改成對應的傳參值,無需修改方法傳參。

methods: {
    categoryClick(index, id) {
        this.currentIndex = index;    // 修改分類列表的樣式
        this.categoryId = id;         // 賦值課程列表對應id
        this.getAllCategoryList()
    },
    // 獲取所有的課程列表
    getAllCategoryList() {
        console.log(this.categoryId);
        // 代碼略
}

  在 getAllCategoryList() 方法中打印 this.categoryId,肯定它的值:

  

  點擊所有打印0,點擊Python打印1,點擊Linux運維打印2。

三、顯示效果

  點擊Linux運維顯示以下:

  

  點擊Go語言顯示以下:

  

相關文章
相關標籤/搜索