什么是Vuex

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

简单来说就是用一个中央状态的仓库state来管理Vue各个组件的状态的工具。

Vuex解决了什么问题

由于Vue的状态参数传递由父组件传递到子组件,子组件不能直接修改父组件的状态,需要通过$emit提交事件的方式来通知父组件更新状态。

这就导致多层嵌套组件和平行组件之前的通信变得非常复杂,而Vuex通过统一的中心状态仓库解决了这个问题。

Vuex的使用

挂载 Vuex

下面是store/index.js

index.js为固定的名称,这样可以在使用import语句时直接这样使用import store from './store/'

store目录名则是为了在main.js中实例化Vue时可以使用缩写。

例如下面的main.js中挂载Vuex实例

 new Vue({
el: '#app',
store,
<!-- 等效于 store:store -->
})

store/index.js 中配置Vuex

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(vuex)

export default new Vuex.Store({
modules: {

},
state: {

},
mutations: {

},
actions: {

},
getters
})

状态 state

通过this.$store.state来获取在Store实例中state属性定义的状态信息

例如获取 count 的值: this.$store.state.count

通常用于组件的computed属性来更新页面上的信息,例如下面

<tempale>
<div>{{count}}<div>
<temaple/>
<script>
export default{

<!-- 省略部分代码 -->

computed: {
count() {
return this.$store.state.count
}
}
}
<script/>

计算状态 getter

如果想通过获取的仓库中的某些状态来计算出一个新的状态,则应该使用getter计算状态。

通过 this.$store.getters来获取在Store实例中getters属性定义的状态计算属性

例如获取通过状态计算得到的 calculateCount 的值:

<tempale>
<div>{{calculateCount}}<div>
<temaple/>
<script>
export default{

computed: {
calculateCount () {
return this.$store.getters.calculateCount
}
}
<!-- 下面是没有使用getter的代码
computed: {
calculateCount () {
return this.$store.state.count.filter(count => count.done).length
}
}
}
-->
<script/>

下面是定义在getters中的状态计算属性calculateCount

每一个定义的 getters 可以接受两个参数 state 和 getters

export default new Vuex.Store({
<!-- 省略部分代码 -->

getters: {
calculateCount: (state, getters) => {
return state.count.filter(count => count.done)
}
}
})

变化 mutation

state 和 getter 只能获取store中的状态和计算状态,要想改变store中的state就需要使用mutation。

通过 this.$store.commit来更改stroe中的state

commit命令有两种提交方式:

1.外置声明提交

声明第一个参数为mutation类型名称,第二个参数为向mutation中传入的参数对象来进行提交(也可以使用变量,通常使用对象)

this.$store.commit('mutation类型名称',{amount:100})

2.内置声明提交

使用一个必须包含type属性的对象来进行提交,其他参数也可以包含在该对象中

this.$store.commit({type:mutation类型名称,amount:100})

下面是定义在mutations中的类型为mutations的变化

export default new Vuex.Store({
<!-- 省略部分代码 -->

mutations: {
increment: (state, parms) => {
state.count + parms.amount
}
}
})

mutations 需要注意的事情

  1. 最好初始化相关的state

  2. 替换或追加属性最好使用ES6的...对象展开符

例如:

state.obj = { ...state.obj, newProp: 123 }
  1. 使用常量来定义mutations类型名称,便于更改和维护,尤其是在大项项目中。

例如:

定义在 mutation-types.js 中的mutations类型常量
export const SOME_MUTATION = 'SOME_MUTATION'

import Vuex from 'vuex'
import { SOME_MUTATION } from './mutation-types'


export default new Vuex.Store({
<!-- 省略部分代码 -->

mutations: {
SOME_MUTATION: (state, parms) => {
state.count + parms.amount
}
}
})

动作 action

由于mutation只能执行同步操作,当使用Ajax进行操作的时候就不行了
这个时候就该action出场了。action没有只能执行同步操作的限制。

定义一个名为increment的action,它会执行类型名为someMutations的mutation。

action的基本流程是:

通过$store.dispath() 触发action 然后再由 action 内执行 commit 来修改state

import Vuex from 'vuex'


export default new Vuex.Store({
<!-- 省略部分代码 -->

actions: {
increment : (context) => {
context.commit('someMutations')
}
}
})

定义的action接受一个参数,该参数与 store 实例具有相同方法和属性的 context 对象,
这样就可以通过context对象来获取store实例中的内容。例如:

context.state 等效于 $store.state
context.mutations 等效于 $store.mutations
context.getters 等效于 $store.getters
context.commit 等效于 $store.commit

由于通常会通过commit提交mutation来修改store的state,可以通过ES6的解构赋值来进行简写。
也就是说下面commit的提交:

import Vuex from 'vuex'

export default new Vuex.Store({
<!-- 省略部分代码 -->

actions: {
increment : (context) => {
context.commit('someMutations')
}
}
})

可以被简写为

import Vuex from 'vuex'

export default new Vuex.Store({
<!-- 省略部分代码 -->

actions: {
increment : ({commit}) => {
commit('someMutations')
}
}
})

通过 this.$store.dispath来触发stroe中的action

和mutation一样,触发action也有两种触发方式:

1.外置声明触发

声明第一个参数为action类型名称,第二个参数为向action中传入的参数对象来进行提交(也可以使用变量,通常使用对象)

this.$store.dispath('action名称',{amount:100})

2.内置声明触发

使用一个必须包含type属性的对象来进行提交,其他参数也可以包含在该对象中

this.$store.dispath({type:action名称,amount:100})

辅助函数

Vuex提供了4个辅助函数配合ES6的扩展运算符来实现函数映射。

mapStatemapGettersmapMutationsmapActions

mapState

mapState()函数可以接受一个对象或者一个字符串数组来进行映射,它返回一个包含尤其生成的computed属性的对象,

这样就可以不必在computed 中自行定义属性了

对象参数映射:

computed: mapState({ count: state => state.count }) 映射为 computed: { count () { return this.$store.state.count }}

对象字符串参数映射:

computed: mapState({ countAlias: ‘count’ }) 映射为 computed: { countAlias () { return this.$store.state.count }}

字符串数组映射,(需要计算属性名与state属性名相同):

computed: mapState([ ‘count’ ]) 映射为 computed: { count () { return this.$store.state.count }}

映射函数:

computed: mapState({ countPlusLocalState (state) { return state.count + this.localCount } }) 映射为

computed: { countPlusLocalState () { return state.count + this.localCount }}

mapGetters

mapMutations

mapActions

模块化 model