Vuex
狀態(tài)管理模式
集中式存儲管理應(yīng)用的所有組件的狀態(tài),以相應(yīng)的規(guī)則保證狀態(tài)以一種可以預(yù)測的方式發(fā)生變化。
容器 store
倉庫包含應(yīng)用中大部分狀態(tài)。
- 響應(yīng)式存儲,組件從 store 中讀取狀態(tài)時,若store 中的狀態(tài)發(fā)生變化,相應(yīng)組件也會相應(yīng)得到高效刷新;
- 不能直接改變 store 中的狀態(tài)。唯一途徑就是顯示提交 mutation -> 可以方便跟蹤每一個狀態(tài)的變化。
創(chuàng)建 store,僅需提供初始 state 對象和一些 mutation:
// 如果在模塊化構(gòu)建系統(tǒng)中,請確保在開頭調(diào)用了 Vue.use(Vuex)
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
}
})
通過 store.state 來獲取狀態(tài)對象,通過 store.commit 方法觸發(fā)狀態(tài)變更:
store.commit('increment')
console.log(store.state.count) // -> 1
核心概念
-
State
單一狀態(tài)樹。Store 倉庫中的 數(shù)據(jù) 狀態(tài) state。
// module1.js
const state = {
count: 0,
firstName: 'Kofe',
lastName: 'Chen'
}
-
Getter
Store 的 計算屬性,其返回值會根據(jù)它的依賴被緩存起來,只有依賴值發(fā)生改變才會重新計算。
// module1.js
const getters = {
// 直接拋出其值
count: state => state.count,
// 根據(jù)依賴
fullName: state => state.firstName + ' ' + state.lastName
}
-
Mutation
更改 Vuex 的 store 中狀態(tài)的唯一 方法 是提交 mutation (類似事件),每個 mutation 都有一個字符串的事件類型(type)和一個回調(diào)函數(shù)(handler)。
回調(diào)函數(shù)就是實際進行狀態(tài)更改的地方,且會接受 state 作為第一個參數(shù)。
// module1.js
const mutations = {
increment(state) {
state.count ++
},
modifyFirstName(state, newName) {
state.firstName = newName
},
modifyLastName(state, newName) {
state.lastName = newName
}
}
-
Action
類似 mutation,Action 提交的是 mutation,但不是直接變更狀態(tài)。Action 可以包含任意 異步操作。
// module1.js
const actions = {
// 第一個參數(shù)是默認(rèn)的 { commit }
changeFullName({ commit }, { firstName, lastName }) {
// 假定 getName 方法返回 promise 對象
// 并且提交 firstName 和 lastName ,如果修改成功則提交 mutation
return getName({ firstName, lastName }).then(res => {
commit('modifyFirstName', res.firstName)
commit('modifyLastName', res.lastName)
})
},
// 與上面的寫法相同,返回的仍然是 promise 對象
async changeFullName({ commit }, { firstName, lastName }) {
let res = await getName({ firstName, lastName })
commit('modifyFirstName', res.firstName)
commit('modifyLastName', res.lastName)
// 這里返回調(diào)用的時候想得到 then 里面的數(shù)據(jù)
return res
}
}
- Module
Vuex 允許將 store 分割成 module,每個模塊擁有自己的 state、mutation、action、getter或甚至是嵌套子模塊。數(shù)據(jù)量大復(fù)雜可以拆分成不同模塊。
// index.js
import module1 from './modules/module1'
import module2 from './modules/module2'
// 如果在模塊化構(gòu)建系統(tǒng)中,請確保在開頭調(diào)用了 Vue.use(Vuex)
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
module1,
module2
}
})
示例代碼文件格式
| -- store
index.js
| -- modules
| -- module1.js
| -- module2.js
module1.js 補充代碼
export default {
state,
getters,
mutations,
actions
}
使用
main.js 中引入 store:
// ...省略
import store from './store'
Vue.config.productionTip = false
new Vue({
el: '#app',
router,
store,
components: { App },
template: '<App/>'
})
組件中使用:
<template>
<div>{{fullName}}</div>
<input v-model="firstName" placeholder="firstName">
<input v-model="lastName" placeholder="lastName" >
<a href="#" @click="onChange">改變?nèi)?lt;/a>
</template>
<script>
import { mapGetters, mapActions } from 'vuex'
export default {
data() {
return {
firstName: '',
lastName: ''
}
},
computed: {
...mapGetters([
'count',
'fullName'
])
},
methods: {
...mapActions([
'changeFullName'
]),
onChange() {
this.changeFullName({ firstName: this.firstName, lastName: this.lastName })
.then(() => {
// ...
})
}
}
}
</script>