閱讀時間預計8分鐘,讀完本文你將收穫如下知識點,記得點贊?哦~
一、啥是Vuex?
Vuex是用來管理Vue的所有元件狀態,說白了就是元件中通訊的一種高階方式。
Vuex官方文件已經講解的非常詳細,建議通讀一遍,本文是自己的學習總結實踐和歸納,有些概念和語句借鑑官方。
二、為什麼使用Vuex?
在之前的文章元件通訊中我們講了元件中的常用通訊方式有props
,$emit/v-on
,$parent / $children & $refs
這三種,他們的侷限性在於只能在父子元件中通訊,不能在兄弟元件中通訊,另外兩種是Bus中央匯流排
、釋出訂閱模式
可以在任意元件之間進行通訊,但是如果在大型專案中難免會有些許瓶頸,元件之間的耦合度較高,那麼這時Vuex
就恰到好處的出現了,他能夠合理的管理各元件中的狀態(通訊,方法捕獲實現,資料傳遞),將狀態從組建中剝離開來,定義和隔離狀態管理中的各種概念並通過強制規則維持檢視和狀態間的獨立性,這樣我們的程式碼將會變得更結構化且易維護。
三、Vuex核心
Vuex
提供一個單例Store
它就相當於一個容器一樣,包含著你應用中的state
公共資料,我們通過單例Store
來統一的按照既定規則來動態的管理這些state
,這就是Vuex
的核心。
1.State
state就是一個純物件,上面有一些狀態掛載,而且一個應用應該只有一個
state
在store.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>
複製程式碼
輸出結果:
2.Getter
可以認為是
store
的計算屬性,就像計算屬性一樣,getter
的返回值會根據它的依賴被快取起來,且只有當它的依賴值發生了改變才會被重新計算。
2.1mapGetter
mapGetter
是getter的一個輔助函式,使用方法和mapState
類似,推薦使用延展...來取值.
3.Mutation
在元件中通過事件方法來進行同步改變Vuex 中的 mutation 非常類似於事件:每個 mutation 都有一個字串的 事件型別 (type) 和 一個 回撥函式 (handler)。這個回撥函式就是我們實際進行狀態更改的地方,並且它會接受 state 作為第一個引數,同步改變state的唯一方法。
store
中的state
,需要通過commit
提交來響應mutation
中的事件方法。
methods: {
add () {
Store.commit('increment', { number: 10 });
},
reduce () {
Store.commit('reduce');
}
}
複製程式碼
另外一種寫法:物件風格的提交方式
推薦使用常量替代 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'
3.1 mapMutation
mapMutation
是mutation
的輔助函式,和state
類似都可以通過...擴充套件運算來進行直接取值。
4.Action
- Action 提交的是
mutation
,而不是直接變更狀態。 - Action 可以包含任意非同步操作。
註冊一個簡單的Action
,並且從外界傳值。
store.dispatch
方法觸發,在Vue元件中:
另外的寫法:引數解構
add({commit}) {
commit('add');
}
複製程式碼
4.1 mapAction
mapAction
是action
的輔助函式,便於在Vue元件中呼叫action裡面的事件.
在Vue元件中,可以通過解構mapAction
的方式將對映
methods: {
...mapActions([
'add',
"reduce"
])
}
複製程式碼
注意此時:用mapActiono
對映方法後需要傳參那麼需要寫在事件觸發的地方上
<button @click="add({number:10})">增加年齡</button>
複製程式碼
4.2 組合 Action
組合Action其實就是非同步處理多個commit
事件,可以相互調動action
,藉助Promise
保證了資料狀態的穩定性和有序性。
官方例項:
在store.js
中
store.dispatch('actionA').then(() => {
})
複製程式碼
在另外一個 action 中可以非同步提交事件:
actions: {
actionB ({ dispatch, commit }) {
return dispatch('actionA').then(() => {
commit('someOtherMutation')
})
}
}
複製程式碼
推薦閱讀:
5.Module
當應用變得非常複雜時,store 物件就有可能變得相當臃腫,為了解決這一問題,我們可以將store
中的五種狀態剝離成單個的模型,然後通過一個入口引入.一般在專案開發中在src
目錄下建立一個store
的目錄然後建立以下檔案
在index.js
中引入所有檔案,統一掛載在Vuex例項上
main.js
中引入index.js
並掛載到例項Vue上
常用專案結構:
├── 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模組
└── ...
複製程式碼
掃一掃下面的二維碼,回覆學習即可免費領取最新前端學習資料,也希望在前端進階的路上,我們一起成長,一起進步!