Vuex
狀態(tài)管理模式
集中式存儲(chǔ)管理應(yīng)用的所有組件的狀態(tài)灌灾,以相應(yīng)的規(guī)則保證狀態(tài)以一種可以預(yù)測(cè)的方式發(fā)生變化室囊。
容器 store
倉(cāng)庫(kù)包含應(yīng)用中大部分狀態(tài)万搔。
- 響應(yīng)式存儲(chǔ)蘸嘶,組件從 store 中讀取狀態(tài)時(shí),若store 中的狀態(tài)發(fā)生變化计雌,相應(yīng)組件也會(huì)相應(yīng)得到高效刷新悄晃;
- 不能直接改變 store 中的狀態(tài)。唯一途徑就是顯示提交 mutation -> 可以方便跟蹤每一個(gè)狀態(tài)的變化凿滤。
創(chuàng)建 store传泊,僅需提供初始 state 對(duì)象和一些 mutation:
// 如果在模塊化構(gòu)建系統(tǒng)中,請(qǐng)確保在開頭調(diào)用了 Vue.use(Vuex)
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
}
})
通過(guò) store.state 來(lái)獲取狀態(tài)對(duì)象鸭巴,通過(guò) store.commit 方法觸發(fā)狀態(tài)變更:
store.commit('increment')
console.log(store.state.count) // -> 1
核心概念
-
State
單一狀態(tài)樹眷细。Store 倉(cāng)庫(kù)中的 數(shù)據(jù) 狀態(tài) state。
// module1.js
const state = {
count: 0,
firstName: 'Kofe',
lastName: 'Chen'
}
-
Getter
Store 的 計(jì)算屬性鹃祖,其返回值會(huì)根據(jù)它的依賴被緩存起來(lái)溪椎,只有依賴值發(fā)生改變才會(huì)重新計(jì)算。
// module1.js
const getters = {
// 直接拋出其值
count: state => state.count,
// 根據(jù)依賴
fullName: state => state.firstName + ' ' + state.lastName
}
-
Mutation
更改 Vuex 的 store 中狀態(tài)的唯一 方法 是提交 mutation (類似事件),每個(gè) mutation 都有一個(gè)字符串的事件類型(type)和一個(gè)回調(diào)函數(shù)(handler)校读。
回調(diào)函數(shù)就是實(shí)際進(jìn)行狀態(tài)更改的地方沼侣,且會(huì)接受 state 作為第一個(gè)參數(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 = {
// 第一個(gè)參數(shù)是默認(rèn)的 { commit }
changeFullName({ commit }, { firstName, lastName }) {
// 假定 getName 方法返回 promise 對(duì)象
// 并且提交 firstName 和 lastName 轧膘,如果修改成功則提交 mutation
return getName({ firstName, lastName }).then(res => {
commit('modifyFirstName', res.firstName)
commit('modifyLastName', res.lastName)
})
},
// 與上面的寫法相同,返回的仍然是 promise 對(duì)象
async changeFullName({ commit }, { firstName, lastName }) {
let res = await getName({ firstName, lastName })
commit('modifyFirstName', res.firstName)
commit('modifyLastName', res.lastName)
// 這里返回調(diào)用的時(shí)候想得到 then 里面的數(shù)據(jù)
return res
}
}
- Module
Vuex 允許將 store 分割成 module兔甘,每個(gè)模塊擁有自己的 state谎碍、mutation、action洞焙、getter或甚至是嵌套子模塊蟆淀。數(shù)據(jù)量大復(fù)雜可以拆分成不同模塊。
// index.js
import module1 from './modules/module1'
import module2 from './modules/module2'
// 如果在模塊化構(gòu)建系統(tǒng)中澡匪,請(qǐ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 補(bǔ)充代碼
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>