小編在項(xiàng)目中,經(jīng)常會使用到Vuex,其實(shí)小編自己只是知道Vuex是為了解決什么痛點(diǎn),但是具體這個東西是怎么回事,小編自己有點(diǎn)迷迷糊糊,昨天小編痛下決心,認(rèn)認(rèn)真真的把Vuex的官網(wǎng)(https://vuex.vuejs.org/zh/)讀了一遍,收獲還是很多的,特地拿出來與大家分享,也希望能在大家今后的面試中,增加一些籌碼和信心。大家還可以關(guān)注我的微信公眾號,蝸牛全棧。
Vuex 是一個專為 Vue.js 應(yīng)用程序開發(fā)的狀態(tài)管理模式。它采用集中式存儲管理應(yīng)用的所有組件的狀態(tài),并以相應(yīng)的規(guī)則保證狀態(tài)以一種可預(yù)測的方式發(fā)生變化。Vuex 也集成到 Vue 的官方調(diào)試工具 devtools extension (opens new window),提供了諸如零配置的 time-travel 調(diào)試、狀態(tài)快照導(dǎo)入導(dǎo)出等高級調(diào)試功能。
這個是官網(wǎng)對Vuex的描述,小編之前的項(xiàng)目經(jīng)常會用Vuex存儲用戶信息,比如當(dāng)前用戶的id,用戶所在部門,頭像等等,這些信息都是通過數(shù)據(jù)接口獲得的數(shù)據(jù),其實(shí)存儲在用戶瀏覽器的Cookie和LocalStorage都是可以的,用的時候,再從本地的相應(yīng)位置獲取,用戶退出的時候,清空對應(yīng)的信息,同樣也可以較少多次請求,并且也解決了多個組件共享數(shù)據(jù)的痛點(diǎn)。但是很多成型的admin都在使用Vuex,同樣對于另一個前端框架大名鼎鼎的React也在用類似的方案(Redux),面臨前端日新月異的發(fā)展,學(xué)會使用Vuex就顯得更為重要。
Vuex主要分為四個部分,State、Getters、Mutations、Actions,小編下面就結(jié)合實(shí)例一一的解釋一下。在正式進(jìn)入Vuex的世界之前,我們需要先安裝Vuex
npm install vuex --save
在我們使用腳手架構(gòu)建項(xiàng)目的時候,需要顯示的在項(xiàng)目入口文件main.js中引入Vuex,并通過Vue.use()來安裝
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
Vuex依賴Promise,還不了解Promise的,可以查看小編之前的文章《ES6中的Promise》一、State
Vuex核心就是一個store,store中的數(shù)據(jù)都存放在State中,可以將State理解成一個大倉庫,大倉庫中存著我們需要共享的數(shù)據(jù)。在組件中,可以通過this.$store獲取State中的數(shù)據(jù),為了保證數(shù)據(jù)的一致性,State中數(shù)據(jù)是不允許直接修改的,改變 store 中的狀態(tài)的唯一途徑就是顯式地提交 (commit)
下面我們來創(chuàng)建一個最簡單的store
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
}
})
現(xiàn)在,你可以通過 store.state 來獲取狀態(tài)對象,以及通過 store.commit 方法觸發(fā)狀態(tài)變更:
store.commit('increment')
console.log(store.state.count) // -> 1
最后,我們需要把store注入到創(chuàng)建的Vue實(shí)例中,就像這樣
new Vue({
el: '#app',
store // 這個位置因?yàn)閷ο蟮膋ey和value一樣,使用es6語法可以簡寫成這樣
})
那么我們?nèi)绾卧?Vue 組件中展示狀態(tài)呢?由于 Vuex 的狀態(tài)存儲是響應(yīng)式的,從 store 實(shí)例中讀取狀態(tài)最簡單的方法就是在計(jì)算屬性(computed)中返回某個狀態(tài):
// 創(chuàng)建一個 Counter 組件
const Counter = {
template: `<div>{{ count }}</div>`,
computed: {
count () {
return store.state.count
}
}
}
我們還可以這樣
const Counter = {
template: `<div>{{ count }}</div>`,
computed: {
count () {
return this.$store.state.count
}
}
}
實(shí)際上以上內(nèi)容,我們就可以正常讀取store中的值了,官方還提供我們一種更簡便的方式:mapState
// 在單獨(dú)構(gòu)建的版本中輔助函數(shù)為 Vuex.mapState
import { mapState } from 'vuex'
export default {
// ...
computed: mapState({
// 箭頭函數(shù)可使代碼更簡練
count: state => state.count,
// 傳字符串參數(shù) 'count' 等同于 `state => state.count`
countAlias: 'count',
// 為了能夠使用 `this` 獲取局部狀態(tài),必須使用常規(guī)函數(shù)
countPlusLocalState (state) {
return state.count + this.localCount
}
})
}
同樣,類似es6對象的擴(kuò)展中,key和value值一樣的時候,可以簡寫,同樣,mapState也提供類似的使用方法
computed: mapState([
// 映射 this.count 為 store.state.count
'count'
])
在es6出現(xiàn)了擴(kuò)展運(yùn)算符的之后,我們可以更加簡便的寫法,也是小編在github上最常見的方式
computed: {
localComputed () { /* ... */ },
// 使用對象展開運(yùn)算符將此對象混入到外部對象中
...mapState({
// ...
})
}
二、Getters
小編個人感覺這個和一些后端語言有類似的地方,比如我們想獲取一個store中數(shù)組的長度,沒有Getters的時候,我們需要在計(jì)算屬性(computed)這么寫
computed: {
doneTodosCount () {
return this.$store.state.todos.filter(todo => todo.done).length
}
}
這個例子還是相對比較簡單的,要是遇上更復(fù)雜的情況,在獲取到State中數(shù)據(jù)之后,還要各種處理,想想一坨坨的js代碼,頭就大,還好,Vuex提供了Getters。我們可以這樣寫
const store = new Vuex.Store({
state: {
todos: [
{ id: 1, text: '...', done: true },
{ id: 2, text: '...', done: false }
]
},
getters: { // 通過Getters將doneTodos暴露出去
doneTodos: state => {
return state.todos.filter(todo => todo.done)
}
}
})
在獲取的時候,這樣就可以獲取到內(nèi)容了,就像這樣
store.getters.doneTodos // -> [{ id: 1, text: '...', done: true }]
Getter 也可以接受其他 getter 作為第二個參數(shù):
getters: {
// ...
doneTodosCount: (state, getters) => {
return getters.doneTodos.length
}
}
store.getters.doneTodosCount // -> 1
我們可以很容易地在任何組件中使用它:
computed: {
doneTodosCount () {
return this.$store.getters.doneTodosCount
}
}
同樣,我們還可以讓Getters結(jié)合es6箭頭函數(shù)返回一個函數(shù),在實(shí)際使用頁面中傳遞參數(shù)來獲取不同的結(jié)果,就類似原生js的過濾器filter一樣
getters: {
// ...
getTodoById: (state) => (id) => {
return state.todos.find(todo => todo.id === id)
}
}
store.getters.getTodoById(2) // -> { id: 2, text: '...', done: false }
和上面mapState類似,Getters也提供了類似的方式
import { mapGetters } from 'vuex'
export default {
// ...
computed: {
// 使用對象展開運(yùn)算符將 getter 混入 computed 對象中
...mapGetters([
'doneTodosCount',
'anotherGetter',
// ...
])
}
}
如果你想將一個 getter 屬性另取一個名字,使用對象形式:
...mapGetters({
// 把 `this.doneCount` 映射為 `this.$store.getters.doneTodosCount`
doneCount: 'doneTodosCount'
})
參考文獻(xiàn):https://vuex.vuejs.org/zh/