在理解Vuex的使用和原理以前首先要知道Vuex是什麼?按照官方的說法,Vuex是專門爲Vuejs應用程序設計的一款狀態管理模式,相似於React中的Redux。它採用集中式存儲管理應用的全部組件的狀態。前端
下面圖片很清晰的展現出了Vuex的組成結構vue
state 是 Vuex 的數據中心,也就是說state是用來存儲數據的。vuex
getters 和 組件的 computed 相似,方便直接生成一些能夠直接用的數據。當組裝的數據要在多個頁面使用時,就可使用 getters 來作。npm
mutations提交更改數據,使用store.commit方法更改state存儲的狀態。數組
Action 提交的是 mutation,而不是直接變動狀態。Action 能夠包含任意異步操做。緩存
npm install vuex --save
複製代碼
方式二: yarn 方式yarn add vuex
複製代碼
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
複製代碼
方式一: this.$store.state獲取bash
經過在根實例中註冊 store 選項,該 store 實例會注入到根組件下的全部子組件中,且子組件能經過 this.$store 訪問到異步
const Counter = {
template: `<div>{{ count }}</div>`,
computed: {
count () {
return this.$store.state.count
}
}
}
複製代碼
方式二: mapState 輔助函數獲取(推薦)函數
當一個組件須要獲取多個狀態時候,將這些狀態都聲明爲計算屬性會有些重複和冗餘。爲了解決這個問題,咱們可使用 mapState 輔助函數幫助咱們生成計算屬性,讓你少按幾回鍵:ui
import { mapState } from "vuex";
export default {
// ...
computed: mapState({
// 箭頭函數可以使代碼更簡練
count: state => state.count,
// 傳字符串參數 'count' 等同於 `state => state.count`
countAlias: 'count',
// 爲了可以使用 `this` 獲取局部狀態,必須使用常規函數
countPlusLocalState (state) {
return state.count + this.localCount
}
})
}
複製代碼
當映射的計算屬性的名稱與 state 的子節點名稱相同時,咱們也能夠給 mapState 傳一個字符串數組。
computed: mapState([
// 映射 this.count 爲 store.state.count
'count'
])
複製代碼
有時候咱們須要從 store 中的 state 中派生出一些狀態,例如對列表進行過濾並計數:
computed: {
doneTodosCount () {
return this.$store.state.todos.filter(todo => todo.done).length
}
}
複製代碼
若是有多個組件須要用到此屬性,咱們要麼複製這個函數,或者抽取到一個共享函數而後在多處導入它——不管哪一種方式都不是很理想。
Vuex 容許咱們在 store 中定義「getter」(能夠認爲是 store 的計算屬性)。就像計算屬性同樣,getter 的返回值會根據它的依賴被緩存起來,且只有當它的依賴值發生了改變纔會被從新計算。
方式一: 經過屬性訪問
store.getters.doneTodos
複製代碼
方式二: 經過方法訪問
你也能夠經過讓 getter 返回一個函數,來實現給 getter 傳參。在你對 store 裏的數組進行查詢時很是有用。
getters: {
// ...
getTodoById: (state) => (id) => {
return state.todos.find(todo => todo.id === id)
}
}
複製代碼
store.getters.getTodoById(2)
複製代碼
注意,getter 在經過方法訪問時,每次都會去進行調用,而不會緩存結果。
方式三: mapGetters 輔助函數獲取(推薦)
import { mapGetters } from 'vuex'
export default {
// ...
computed: {
// 使用對象展開運算符將 getter 混入 computed 對象中
...mapGetters([
'doneTodosCount',
'anotherGetter',
// ...
])
}
}
複製代碼
若是你想將一個 getter 屬性另取一個名字,使用對象形式:
mapGetters({
// 把 `this.doneCount` 映射爲 `this.$store.getters.doneTodosCount`
doneCount: 'doneTodosCount'
})
複製代碼
上面咱們說了更改 Vuex 的 store 中的狀態的惟一方法是提交 mutation,Vuex 中的 mutation 很是相似於事件:每一個 mutation 都有一個字符串的 事件類型 (type) 和 一個 回調函數 (handler)。這個回調函數就是咱們實際進行狀態更改的地方,而且它會接受 state 做爲第一個參數。
使用常量替代 Mutation 事件類型
// mutation-types.js
export const SOME_MUTATION = 'SOME_MUTATION'
複製代碼
// store.js
import Vuex from 'vuex'
import { SOME_MUTATION } from './mutation-types'
const store = new Vuex.Store({
state: { ... },
mutations: {
// 咱們可使用 ES2015 風格的計算屬性命名功能來使用一個常量做爲函數名
[SOME_MUTATION] (state) {
// mutate state
}
}
})
複製代碼
固然使用常量代替Mutation事件類型也不是必須的,若是你不喜歡,你徹底能夠不這樣作。
在組件中提交 Mutation
你能夠在組件中使用 this.$store.commit('xxx') 提交 mutation,或者使用 mapMutations 輔助函數將組件中的 methods 映射爲 store.commit 調用(須要在根節點注入 store)。
import { mapMutations } from 'vuex'
export default {
// ...
methods: {
...mapMutations([
'increment', // 將 `this.increment()` 映射爲 `this.$store.commit('increment')`
// `mapMutations` 也支持載荷:
'incrementBy' // 將 `this.incrementBy(amount)` 映射爲 `this.$store.commit('incrementBy', amount)`
]),
...mapMutations({
add: 'increment' // 將 `this.add()` 映射爲 `this.$store.commit('increment')`
})
}
}
複製代碼
Action的註冊
Action 函數接受一個與 store 實例具備相同方法和屬性的 context 對象,所以你能夠調用 context.commit 提交一個 mutation,或者經過 context.state 和 context.getters 來獲取 state 和 getters。當咱們在以後介紹到 Modules 時,你就知道 context 對象爲何不是 store 實例自己了。
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
actions: {
increment (context) {
context.commit('increment')
}
}
})
複製代碼
分發 Action
// 以載荷形式分發
store.dispatch('incrementAsync', {
amount: 10
})
// 以對象形式分發
store.dispatch({
type: 'incrementAsync',
amount: 10
})
複製代碼
在組件中分發 Action
你在組件中使用 this.$store.dispatch('xxx') 分發 action,或者使用 mapActions 輔助函數將組件的 methods 映射爲 store.dispatch 調用(須要先在根節點注入 store)
import { mapActions } from 'vuex'
export default {
// ...
methods: {
...mapActions([
'increment', // 將 `this.increment()` 映射爲 `this.$store.dispatch('increment')`
// `mapActions` 也支持載荷:
'incrementBy' // 將 `this.incrementBy(amount)` 映射爲 `this.$store.dispatch('incrementBy', amount)`
]),
...mapActions({
add: 'increment' // 將 `this.add()` 映射爲 `this.$store.dispatch('increment')`
})
}
}
複製代碼
至此Vuex的使用及原理就介紹到這裏,若是還有不一樣理解的小夥伴們還請下發留言。若是有寫的很差的地方還請多多指教。我會繼續更新有關前端的技術文章的。