什么是vuex?
vuex 是一個專為 Vue.js 應(yīng)用程序開發(fā)的狀態(tài)管理模式。它采用集中式存儲管理應(yīng)用的所有組件的狀態(tài),并以相應(yīng)的規(guī)則保證狀態(tài)以一種可預(yù)測的方式發(fā)生變化。
這是vuex官網(wǎng)的解釋。我們把它理解為在data中的屬性需要共享給其他vue組件使用的部分,即data中需要共用的屬性。
vuex的核心概念
1. this.$store:我們可以通過this.$store在vue的組件中獲取vuex的實例。
2. State:vuex中的數(shù)據(jù)源,我們可以通過this.$store.state獲取我們在vuex中聲明的全局變量的值。
3. Getter:相當(dāng)于vue中的computed,及計算屬性,可以用于監(jiān)聽、計算 state中的值的變化。
4. Mutation:vuex中去操作數(shù)據(jù)的方法(只能同步執(zhí)行)。
5. Action:用來操作Mutation 的動作,他不能直接去操作數(shù)據(jù)源,但可以把mutation變?yōu)楫惒降摹?
6. Module:模塊化,當(dāng)應(yīng)用足夠大的時候,可以把vuex分成多個子模塊。
上手vuex
用
vue-cli構(gòu)建一個項目,用命令npm install vuex --save來安裝vuex-
在src文件夾下新建一個
vuex文件夾,并在文件夾下新建store.js文件
配置
main.js
import App from './App'
import router from './router'
import vuex from 'vuex'
Vue.use(vuex)
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
render: h => h(App)
})
- 配置
store.js
import Vue from 'vue'
import vuex from 'vuex'
Vue.use(vuex)
const state={
count:1
}
export default new vuex.Store({
state
})
- 在components新建一個
count.vue組件,先引入,再注冊,最后調(diào)用
<template>
<div>
{{$store.state.count}} <!-- 調(diào)用 -->
</div>
</template>
<script>
import store from '@/vuex/store' //引入
export default {
store //注冊
}
</script>
<style>
</style>

- 在定義兩個方法來改變
state中的值
import Vue from 'vue'
import vuex from 'vuex'
Vue.use(vuex)
const state={
count:1
}
const mutations={
add(state){ //此處的state是上面的state對象
state.count++
},
reduce(state) {
state.count--
}
}
//用export default 暴露,讓外部可以使用
export default new vuex.Store({
state,
mutations
})
- 在組件中調(diào)用mutations的方法,要以commit的方式調(diào)用
<template>
<div>
{{$store.state.count}}
<div>
<button @click="$store.commit('add')">+</button>
<button @click="$store.commit('reduce')">-</button>
</div>
</div>
</template>
<script>
import store from '@/vuex/store'
export default {
store
}
</script>
<style>
</style>

從圖中可以看到,已經(jīng)實現(xiàn)了對vuex中的count加減操作
訪問state的三種方式
把stroe.js中的值,賦值給我們模板里data中的值,有三種賦值方式:
1. 通過computed的計算屬性直接賦值
computed屬性可以在輸出前,對data中的值進行改變,我們就利用這種特性把store.js中的state值賦值給我們模板中的data值。
export default {
store,
computed:{
count(state){
return this.$store.state.count
}
}
}
同時將模板中的$store.state.count改為count,效果不變
2. 通過mapState的對象來賦值
先引入mapState
import {mapState} from 'vuex'
再修改成如下代碼:
computed:mapState({
count(state){
return state.count
}
})
3. 通過mapState的數(shù)組來賦值
computed:mapState(['count'])
這是最簡單的寫法,也是開發(fā)中最常用的方法
Mutations
接下來修改一下mutations中的add方法,給它加個參數(shù)
const mutations={
add(state,x){
state.count+=x
},
reduce(state) {
state.count--
}
}
在模板中相應(yīng)修改:
<div>
<button @click="$store.commit('add',10)">+</button>
<button @click="$store.commit('reduce')">-</button>
</div>

類似之前的
state的屬性的調(diào)用,mutations的方法調(diào)用也很麻煩,沒有人會喜歡用$store.commit()去調(diào)用方法
模板獲取Mutations方法
先引入mapMutations
import {mapState,mapMutations} from 'vuex'
在methods中加入mapMutations的方法
methods:mapMutations(['add','reduce'])
最后修改模板,就跟平時的調(diào)用方法一樣了
<div>
<button @click="add(10)">+</button>
<button @click="reduce">-</button>
</div>
getters計算過濾操作
對count進行計算屬性的操作,讓它輸出前先加上100
import Vue from 'vue'
import vuex from 'vuex'
Vue.use(vuex)
const state={
count:1
}
const mutations={
add(state,x){
state.count+=x
},
reduce(state) {
state.count--
}
}
const getters={
count(state){
return state.count+=100
}
}
//用export default 暴露,讓外部可以使用
export default new vuex.Store({
state,
mutations,
getters
})
state和getters都是通過computed屬性輸出的,所以當(dāng)getters的介入會覆蓋掉state,所以使用es6的擴展運算符…
computed:{
...mapState(['count']),
count(){
return this.$store.getters.count
}
}

測試一下會發(fā)現(xiàn)每次都是+110,是因為點擊一下,先通過
getters計算得到新的state(此時已經(jīng)+100) 然后由mutation改變+10
用mapGetters簡化模板寫法
先引入mapGetters
import {mapState,mapMutations,mapGetters} from 'vuex'
修改成如下代碼:
computed:{
...mapState(['count']),
...mapGetters(['count'])
}
Actions異步修改狀態(tài)
actions和之前講的mutations功能基本一樣,不同點是,actions是異步的改變state狀態(tài),而mutations是同步改變狀態(tài)。
import Vue from 'vue'
import vuex from 'vuex'
Vue.use(vuex)
const state={
count:1
}
const mutations={
add(state,x){
state.count+=x
},
reduce(state) {
state.count--
}
}
const getters={
count(state){
return state.count+=100
}
}
const actions={
actions_add(context){
context.commit('add',10)
},
actions_reduce({commit}){
commit('reduce')
}
}
//用export default 暴露,讓外部可以使用
export default new vuex.Store({
state,
mutations,
getters,
actions
})
兩個方法的傳參不同:
-
ontext:上下文對象,即store本身 -
{commit}:直接把commit對象傳遞過來,更加清晰
模板使用Actions方法
引入mapActions
import {mapState,mapMutations,mapGetters,mapActions} from 'vuex'
在methods中寫入:
methods:{
...mapMutations(['add','reduce']),
...mapActions(['actions_add','actions_reduce'])
}
最后在模板中調(diào)用方法
<div>
<button @click="actions_add(10)">+</button>
<button @click="actions_reduce">-</button>
</div>
Module模塊組
隨著項目的復(fù)雜性增加,共享的狀態(tài)越來越多,此時就需要對狀態(tài)進行分組,分組后再進行按組編寫,實現(xiàn)狀態(tài)管理器的模塊組操作。
新增兩個文件夾,并且都新增一個store.js

在
test1/store.js中寫入
import Vue from 'vue'
import vuex from 'vuex'
Vue.use(vuex)
const state = {
name: 'test1'
}
export default new vuex.Store({
state
})
復(fù)制test2/store.js中,修改name為test2
import Vue from 'vue'
import vuex from 'vuex'
Vue.use(vuex)
const state = {
name: 'test2'
}
export default new vuex.Store({
state
})
在根目錄的store.js中引入這兩個模塊
import Vue from 'vue'
import vuex from 'vuex'
import modules1 from './test1/store'
import modules2 from './test2/store'
Vue.use(vuex)
export default new vuex.Store({
modules: {
modules1,
modules2
}
})
最后在模板中使用
<template>
<div>
{{name1}}
{{name2}}
</div>
</template>
<script>
import store from '@/vuex/store'
import {mapState} from 'vuex'
export default {
store,
computed:{
...mapState({
name1:({modules1})=>modules1.name,
name2:({modules2})=>modules2.name,
}),
}
}
</script>
<style>
</style>

