Vue 5 -- axios、vuex

1、內容回顧

一、webpack(前端中工做,項目上線以前對整個前端項目優化)javascript

  - entry:整個項目的程序入口(main.js或index.js);css

  - output:輸出的出口;html

  - loader:加載器,對es6代碼的解析,babel-loader(官網:https://www.babeljs.cn/)是瀏覽器支持es6, css-loader解析css文件,style-loader 將css代碼添加一個style標籤插入header標籤中,url-loader等等;前端

  - plugins:有不少,好比html-webpack-plugin,醜陋等等;vue

2、vue項目中常見問題

       咱們已經學過如何使用腳手架建立一個vue項目,接下來咱們介紹一下vue項目中的常見問題。java

一、使用vue-cli腳手架和webpack模板生成一個項目(以項目名爲luffy-project爲例),步驟以下:

1
2
3
vue init webpack luffy-project   // 建立項目(使用單頁面應用就安裝vue-router,其餘選no)
cd luffy-project             // 進入項目所在目錄
npm run dev       // 啓動項目

二、警告:property or methods "xxx" not defined

       出現這個的警告信息,通常是由於你在template中使用了某些數據屬性或者方法,但js中沒有定義。node

三、錯誤:module not found

       出現這個信息表示模塊找不到,通常咱們使用的模塊有兩種,一種是npm社區下載的模塊(如vue),使用時直接導入(如import Vue from 'vue')便可,這種通常不會出錯;另外一種是咱們本身寫的模塊,錯誤每每容易出如今這裏,不是名字寫錯,就是路徑不對。jquery

       注意:還有就是出現了不是本身寫的某個模塊出現錯誤,這時能夠嘗試把node_modules文件夾刪除,再使用下面命令下載項目依賴的包:webpack

npm install    // 下載項目依賴的包,生成node_modules文件夾

3、axios

       axios至關於jquery的ajax,官網:https://www.kancloud.cn/yunye/axios/234845ios

  將axios掛載到vue的原型上,那麼在各個組件中都能使用,由於面向對象(繼承),以下:

  Axios 是一個基於 promise(es6的語法,參考網址:http://es6.ruanyifeng.com/#docs/promise) 的 HTTP 庫,能夠用在瀏覽器和 node.js 中。

  // 下載到項目中

1
npm install axios -S

  // 使用方式以下:

  // 執行GET請求:

// 爲給定 ID 的 user 建立請求
axios.get('/user?ID=12345')
      .then(function (response) {
        console.log(response);
     })
      .catch(function (error) {
        console.log(error);
     });

// 可選地,上面的請求能夠這樣作
axios.get('/user', {
    params: {
      ID: 12345
    }
  })
  .then(function (response) {
     console.log(response);
  })
  .catch(function (error) {
     console.log(error);
  });

  // 執行post請求

axios.post('/user', {
     firstName: 'Fred',
     lastName: 'Flintstone'
  })
  .then(function (response) {
     console.log(response);
  })
  .catch(function (error) {
     console.log(error);
  });

一、在項目中引用

  由於不少模塊都要用axios(與後端交互的一項技術),因此咱們能夠將axios掛載在Vue的原型上,這樣,由於面向對象的繼承特色,各個子組件均可以使用。掛載方式以下:

// main.js中
import Axios from 'axios'   // npm下載的直接引入axios
Vue.prototype.$https = Axios   // 將axios對象掛載到Vue原型上

  注意:必定不要使用Vue.use(),基於Vue的才須要Vue.use(),axios是一個基於es6的知識點,與vue沒有關係,不依賴vue,只是vue開發者不想使用jquery庫,因此使用axios向後臺發請求。

  咱們能夠指定將被用在各個請求的配置默認值,全局的axios默認值有以下幾個:

  axios.defaults.baseURL = 'https://api.example.com';
  axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
  axios.defaults.headers.post['Content-Type'] = 'application/x-www.form-urlencoded';

二、項目示例 - 路飛學城官網的免費課程組件相關代碼

// main.js
  import Vue from 'vue'
  import App from './App'
  import router from './router'
  import Axios from 'axios'
  Vue.prototype.$https = Axios;
  // 設置公共的url
  Axios.defaults.baseURL = 'https://www.luffycity.com/api/v1/';
  Vue.config.productionTip = false;

  /* eslint-disable no-new */
  new Vue({
      el: '#app',
      router,
      components: { App },
      template: '<App/>'
  })
// course.vue
  <template>
  <div>
    <div class="categoryList">
      <span @click="clickHandler(index, item.id)" 
    :class="{active:index===currentIndex}" 
    v-for="(item,index) in categoryList" :key="item.id">
    {{ item.name }}
      </span>
    </div>
    <div class="course">
      <ul>
        <li v-for="(course) in courseList" :key="course.id">
          <h3>{{ course.name }}</h3>
        </li>
      </ul>
    </div>
  </div>
  </template>

  <script>
  export default {
    name:'Course',
    data(){
      return {
        categoryList:[],   // 分類列表
        currentIndex:0,
        courseList:[],   // 課程列表
        categoryId:0     // 默認所有課程id
      }
    },
    methods:{
      // 先在methods中聲明函數-獲取課程分類列表的函數
      getCategoryList(){
        this.$https.get('course_sub/category/list/')
          .then((res) => {
            console.log(res);
            let data = res.data;
            if (data.error_no === 0){
              this.categoryList = data.data;
              let obj = {
                id:0,
                name:'所有',
                category:0
              };
              this.categoryList.unshift(obj)
            }

          })
          .catch((err) => {
            console.log(err);
          })
      },
      // 獲取課程列表
      getCourseList(){
        this.$https.get(`courses/?sub_category=${this.categoryId}`)
          .then((res)=>{
            var data = res.data;
            this.courseList = data.data;
          })
          .catch((err)=>{
            console.log(err)
          })
      },

      clickHandler(index, categoryId){
        this.currentIndex = index;   // 分類列表點擊對應分類變色
        this.categoryId = categoryId;
        this.getCourseList();  // 發送請求
      }
    },
    created(){
      // 組件建立完成調用函數-使用axios向接口請求課程列表數據
      this.getCategoryList()
    }
  }
  </script>

  <style scoped>
  .active{
    color: red;
  }
  </style>

4、vuex

       單向數據流概念的簡單表示,以下圖:

  vuex(至關於一個store)有五大將:state、mutations、actions、getters、modules,前三個重要。

       各個組件能夠經過computed監聽vuex中的state中的數據屬性,修改state中屬性的惟一方法是提交mutations(同步)中的方法,actions中的方法都是異步的。

一、將vuex下載到項目中:

1
>>> npm install vuex -S

二、組件使用store中的值:

       1)使用Vuex的Store方法建立一個store實例對象

import Vuex from 'vuex'
  Vue.use(Vuex);  // 模塊化開發要Vue.use()
  const store = new Vuex.Store({
          state:{
                num: 1
          },
          mutations:{
                // 同步方法
          },
          actions:{
                // 異步方法
          }
  })

       2)將store掛載到Vue實例下        

new Vue({
       el: '#app',
       router,
       store,   // store實例掛載到Vue實例,各個組件都能經過this.$store使用
       components: { App },
       template: '<App/>'
  })

       3)在各組件中經過computed使用store的state中定義的數據屬性

// Home組件中使用
    <template>
          <div>
            <h1>我是首頁{{ myNum }}</h1>
            <Son></Son>
          </div>
    </template>

    <script>
    import Son from './Son'
    export default {
          name: 'Home',
          components:{Son},
          computed:{
            myNum:function () {
                  return this.$store.state.num;
            }
          }
    }
    </script>

    <style scoped></style>
// Son組件(是Home組件的子組件)中使用
    <template>
          <div>
            <h1>我是Son組件的{{ mySonNum }}</h1>
          </div>
    </template>

    <script>
    export default {
          name: 'Son',
          computed:{
            mySonNum:function () {
                  return this.$store.state.num;
            }
          }
    }
    </script>

    <style scoped></style>

三、組件修改store中的值

       1)建立store實例對象,並掛在store到Vue實例

import Vuex from 'vuex'
  Vue.use(Vuex);  // 模塊化開發要Vue.use()
  const store = new Vuex.Store({
          state:{
            num: 1
          },
          // mutations中定義同步方法,默認傳遞一個state
          mutations:{
            setMutaNum(state, val){
                  state.num += val;
            },
            setMutaAsyncNum(state, val){
                  state.num += val;
            }
          },
          // actions中定義異步方法
          actions:{
            // 方法都默認傳遞一個context,就是store
            setActionNum(context, val){
                  context.commit('setMutaNum', val);
            },

            setActionAsyncNum(context, val){
                  setTimeout(()=>{
                context.commit('setMutaAsyncNum', val)
                  },1000)
            }

          }
  })

  new Vue({
          el: '#app',
          router,
          store,
          components: { App },
          template: '<App/>'
  })

    2)在Son組件中觸發actions方法修改store中的值(同步和異步)

<template>
      <div>
            <h1>我是Son組件的{{ mySonNum }}</h1>
            <button @click="addNum">同步修改</button>
            <button @click="addAsyncNum">異步修改</button>
      </div>
  </template>

  <script>
    export default {
          name: 'Son',
          methods:{
            addNum(){
                  // 不要直接修改state中的狀態,要經過commit方法提交
                  // commit()第一個參數是觸發store的mutations中的方法名
                  // 第二個參數給觸發的方法傳遞的值
                  this.$store.dispatch('setActionNum', 2)
                },
            addAsyncNum(){
                  this.$store.dispatch('setActionAsyncNum', 3)
            }
          },
          computed:{
            mySonNum:function () {
                  return this.$store.state.num;
            }
          }
    }
  </script>

  <style scoped></style>

四、vuex的actions中使用axios請求數據

  

   1)課程詳情組件CourseDetail.vue代碼以下:

<template>
          <div>
            <div class="">
                  <h2>我是課程詳情組件</h2>
              <p v-for="value in courseDesc">{{ value }}</p>
            </div>
          </div>
  </template>

  <script>
      export default {
            name:'CourseDetail',
            created(){
              // https://www.luffycity.com/api/v1/course/3
              console.log(this.$route.params.courseid);
              // 組件建立則向觸發發送axios請求
              this.$store.dispatch('course_top', this.$route.params.courseid)
            },
            computed:{
              // 獲取store中的數據,數據是由axios請求而來的
              courseDesc(){
                return this.$store.state.courseDesc
              }
            }
      }
  </script>

  <style scoped>
      .active{
            color: red;
      }
  </style>

  2)建立store實例對象,代碼以下:     

import Vuex from 'vuex'
  Vue.use(Vuex);  
  const store = new Vuex.Store({
         state:{
            num: 1,
            courseDesc:null
          },
          mutations:{
            course_top(state, data){
                  state.courseDesc = data
            }
          },
          actions:{
            course_top(context, courseId){
            // 異步:發送axios請求
                  Axios.get(`course/${courseId}/top/`)
                .then((res)=>{
                      let data = res.data.data;
                      context.commit('course_top', data)
                })
                .catch((err)=>{
                      console.log(err)
                })
            }
          }
  })

5、補充知識點

一、v-for必定要加key

       演示以下代碼(分別在有key和沒有key的狀況下點擊按鈕):

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>v-for中的key</title>
    <style>
        .userList {
            border: 1px solid red;
            margin: 20px 0;
            padding: 10px 10px;
        }
    </style>
</head>
<body>
<div id="app"></div>
<script type="text/javascript" src="vue.js"></script>
<script type="text/javascript" src="lodash.js"></script>
<script type="text/javascript">

    Vue.component('my-com', {
        template: `
            <div class = 'userList'>

               <div class = 'content'>
                  <h3>{{obj.name}}</h3>
                  <p>{{obj.content}}</p>
               </div>
               <div class="control">
                  <input  placeholder="請輸入你的名字" />
               </div>
            </div>

         `,
        props: {
            obj: Object
        }
    });
    var App = {
        data() {
            return {
                datas: [
                    {id: 1, name: '張三', content: '我是張三'},
                    {id: 2, name: '李四', content: '我是李四'},
                    {id: 3, name: '王五', content: '我是王五'},
                ]
            }
        },
        template: `
            <div>
               <button @click = 'shuffle1'>shuffle</button>
               <my-com v-for = '(obj,index) in datas' :obj = 'obj' :key = 'obj.id'></my-com>
            </div>
         `,
        methods: {
            shuffle1() {
                console.log(_.shuffle());
                this.datas = _.shuffle(this.datas);
            }
        }
    }

    new Vue({
        el: '#app',
        data: {},
        components: {
            App
        },
        template: `<App />`
    });
</script>

</body>
</html>

Code
View Code

二、js中數組的splice方法

var arr = ['alex', 'wusir', 'egon', 'sylar']

  // arr.splice(開始位置索引, 刪除個數, 插入元素)

  arr.splice(1, 2)   
  // 索引從1開始,刪除2個,返回刪除元素列表,即['wusir', 'egon']
  // 原數組arr爲  ['alex', 'sylar']

  arr.splice(0, 0, '張三', '李四')   
  // 索引從0開始,刪除0個元素,即不刪除任何元素,返回[]數組,
  // arr變爲['張三', '李四', 'alex', 'sylar']

       總結:能夠作增刪改操做。

三、Vue模塊化開發中,如何註冊全局組件

       假設已經定義了一個組件Header.vue並拋出,在全局的main.js下按以下方式寫:

  import Header from '@/components/Header/Header'
  Vue.component(Header.name, Header);

     這樣,Header組件就是全局組件了,在任意組件中直接使用便可。

相關文章
相關標籤/搜索