Vue從甜小白到皮大佬系列(八) Vuex

極客James發表於2019-09-06

? Vue構建大型單頁面電商應用 開源啦!點我看原始碼??

閱讀時間預計8分鐘,讀完本文你將收穫如下知識點,記得點贊?哦~

Vue從甜小白到皮大佬系列(八) Vuex

一、啥是Vuex?

Vuex是用來管理Vue的所有元件狀態,說白了就是元件中通訊的一種高階方式。

Vuex官方文件已經講解的非常詳細,建議通讀一遍,本文是自己的學習總結實踐和歸納,有些概念和語句借鑑官方。

二、為什麼使用Vuex?

在之前的文章元件通訊中我們講了元件中的常用通訊方式有props,$emit/v-on,$parent / $children & $refs這三種,他們的侷限性在於只能在父子元件中通訊,不能在兄弟元件中通訊,另外兩種是Bus中央匯流排釋出訂閱模式可以在任意元件之間進行通訊,但是如果在大型專案中難免會有些許瓶頸,元件之間的耦合度較高,那麼這時Vuex就恰到好處的出現了,他能夠合理的管理各元件中的狀態(通訊,方法捕獲實現,資料傳遞),將狀態從組建中剝離開來,定義和隔離狀態管理中的各種概念並通過強制規則維持檢視和狀態間的獨立性,這樣我們的程式碼將會變得更結構化且易維護。

三、Vuex核心

Vuex提供一個單例Store它就相當於一個容器一樣,包含著你應用中的state公共資料,我們通過單例Store來統一的按照既定規則來動態的管理這些state,這就是Vuex的核心。

1.State

state就是一個純物件,上面有一些狀態掛載,而且一個應用應該只有一個statestore.js

export default new Vuex.Store({
 state : {//初始狀態
    name:'極客James', 
    height:180,
    age:27
  } 
})
複製程式碼

1.1mapState:

使用 mapState 輔助函式幫助我們生成計算屬性,在需要通訊的元件中通過import {mapState} from 'vuex'引入輔助函式,然後要在計算屬性computed鉤子裡面進行資料的對映。

mapState輔助函式使用的三種方式:

  • 第一種:計算屬性通過箭頭函式取返回值
computed:mapStates({
    name:state=>state.name,
    height:state=>state.name,
    age:state=>state.age
})
複製程式碼
  • 第二種方法:利用ES6的...延展特性 (推薦做法)
computed:{
    ...mapState([
        'name',
        'height',
        'age'
    ])
}
複製程式碼
  • 第三種方法:利用ES6的...延展特性通過物件取值
computed:{
    ...mapState({
        name:state=>state.name,
        height:state=>state.height,
        age:state=>state.age
    })
}
複製程式碼

在元件中取資料

<template>
  <div class="app">
    <div>我是store裡面的資料姓名:{{name}}</div>
    <div>我是store裡面的資料年齡:{{age}}</div>
    <div>我是store裡面的資料身高:{{height}}</div>
  </div>
</template>
複製程式碼

輸出結果:

Vue從甜小白到皮大佬系列(八) Vuex

2.Getter

可以認為是 store 的計算屬性,就像計算屬性一樣,getter 的返回值會根據它的依賴被快取起來,且只有當它的依賴值發生了改變才會被重新計算。

2.1mapGetter

mapGetter是getter的一個輔助函式,使用方法和mapState類似,推薦使用延展...來取值.

3.Mutation

Vuex 中的 mutation 非常類似於事件:每個 mutation 都有一個字串的 事件型別 (type) 和 一個 回撥函式 (handler)。這個回撥函式就是我們實際進行狀態更改的地方,並且它會接受 state 作為第一個引數,同步改變state的唯一方法。

Vue從甜小白到皮大佬系列(八) Vuex
在元件中通過事件方法來進行同步改變store中的state,需要通過commit提交來響應mutation中的事件方法。

methods: {
add () {
  Store.commit('increment', { number: 10 });
},
reduce () {
  Store.commit('reduce');
}
}

複製程式碼

另外一種寫法:物件風格的提交方式

Vue從甜小白到皮大佬系列(八) Vuex
推薦使用常量替代 Mutation 事件型別

還記得在元件通訊中講到的釋出訂閱方法進行元件間通訊,使用常量來定義事件型別嗎?在Vuex中也是非常推薦使用此辦法的,將mutation中的事件常量整合到一個資料夾mutation-type.js中,通過export方式匯出.

mutation-type.js

export const ADD = 'ADD'
export const REDUCE = 'REDUCE'
複製程式碼

store.js中引入import {ADD,REDUCE} from './mutation-type.js'

import {ADD,REDUCE} from './mutation-type.js'
mutation:{
    [ADD](state,payload) {
        state.age += payload.number;
    },
    [REDUCE](state,payload) {
        state.age --;
    }
}
複製程式碼

同樣的在需要的元件中引入import {ADD,REDUCE} from './mutation-type.js'

Vue從甜小白到皮大佬系列(八) Vuex

3.1 mapMutation

mapMutationmutation的輔助函式,和state類似都可以通過...擴充套件運算來進行直接取值。

Vue從甜小白到皮大佬系列(八) Vuex

4.Action

  • Action 提交的是 mutation,而不是直接變更狀態。
  • Action 可以包含任意非同步操作。

註冊一個簡單的Action,並且從外界傳值。

Vue從甜小白到皮大佬系列(八) Vuex
Action 通過 store.dispatch方法觸發,在Vue元件中:

Vue從甜小白到皮大佬系列(八) Vuex

另外的寫法:引數解構

add({commit}) {
    commit('add');
}
複製程式碼

4.1 mapAction

mapActionaction的輔助函式,便於在Vue元件中呼叫action裡面的事件. 在Vue元件中,可以通過解構mapAction的方式將對映

 methods: {
     ...mapActions([
      'add',
      "reduce"
    ])
}
複製程式碼

注意此時:用mapActiono對映方法後需要傳參那麼需要寫在事件觸發的地方上

<button @click="add({number:10})">增加年齡</button>
複製程式碼

4.2 組合 Action

組合Action其實就是非同步處理多個commit事件,可以相互調動action,藉助Promise保證了資料狀態的穩定性和有序性。

官方例項:

store.js

Vue從甜小白到皮大佬系列(八) Vuex
在Vue元件中:

store.dispatch('actionA').then(() => {
 
})
複製程式碼

在另外一個 action 中可以非同步提交事件:

actions: {
  actionB ({ dispatch, commit }) {
    return dispatch('actionA').then(() => {
      commit('someOtherMutation')
    })
  }
}
複製程式碼

推薦閱讀:

MDN Promise

async / await

5.Module

當應用變得非常複雜時,store 物件就有可能變得相當臃腫,為了解決這一問題,我們可以將store中的五種狀態剝離成單個的模型,然後通過一個入口引入.一般在專案開發中在src目錄下建立一個store的目錄然後建立以下檔案

Vue從甜小白到皮大佬系列(八) Vuex

index.js中引入所有檔案,統一掛載在Vuex例項上

Vue從甜小白到皮大佬系列(八) Vuex
main.js中引入index.js並掛載到例項Vue上

Vue從甜小白到皮大佬系列(八) Vuex

常用專案結構:

├── index.html
├── main.js
├── api
│   └── ... # 抽取出API請求
├── components
│   ├── App.vue
│   └── ...
└── store
    ├── index.js          # 我們組裝模組並匯出 store 的地方
    ├── state.js          # 根級別的 state
    ├── actions.js        # 根級別的 action
    ├── getter.js         # 根級別的 getter
    ├── mutations.js      # 根級別的 mutation
    ├── mutations-type.js # mutation事件常數名
    └── modules
        ├── a.js       # a模組
        └── b.js       # b模組
        └── ...
    
複製程式碼

掃一掃下面的二維碼,回覆學習即可免費領取最新前端學習資料,也希望在前端進階的路上,我們一起成長,一起進步!

Vue從甜小白到皮大佬系列(八) Vuex

相關文章