快速学一遍vue的状态管理模式 -- Vuex
Vuex介绍
在制作工程量比较大的vue项目时,经常会遇到各个组件需要操作调用相同的数据的情况。
在应用时,我们可以采用父子组件之间相互传值采用props来进行数据的获取和传递,或者使用store 模式。但是数据量越大,需要管理的数据源越多,那就比较适合vuex的使用了。

按照官方的说法:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
普通状态管理模式
一般而言状态自管理应用包含以下几个部分:
state,驱动应用的数据源;
view,以声明方式将 state 映射到视图;
actions,响应在 view上的用户输入导致的状态变化。

但是当项目中有多个组件要调用和修改这些数据状态时,这种单向的数据流结构就很容易被破坏
原因如下:
多个视图依赖于同一状态。传参的方法对于多层嵌套的组件将会非常繁琐,并且对于兄弟组件间的状态传递无能为力
来自不同视图的行为需要变更同一状态。经常会采用父子组件直接引用或者通过事件来变更和同步状态的多份拷贝。以上的这些模式非常脆弱,通常会导致无法维护的代码。
vuex管理模式
vuex是以一个全局单例模式来管理各种不同的数据源和状态。在这种模式下,我们的组件树构成了一个巨大的“视图”,不管在树的哪个位置,任何组件都能获取状态或者触发行为。通过定义和隔离状态管理中的各种概念并通过强制规则维持视图和状态间的独立性,我们的代码将会变得更结构化且易维护。
vuex安装
npm安装:
vuex也支持标签导入
在模块化的打包项目当中,使用vuex需要import导入后,使用use调用vuex
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
如果使用标签,则无需这些过程,直接使用即可。
vuex核心
State
对于需要多个组件都能操纵的数据,可以创建vuex后写入state当中
在vue cli项目当中的main.js中引入Vuex后,创建一个Vuex.Store示例,定义时在state中写入变量数据
const store = new Vuex.Store({
state: {
data1: '可以被多组件操作的数据',
......
}
})
可以在组件或者其子组件当中使用获取到变量值,其实可以在子组件中直接对变量data1进行修改,但是不太推荐使用这种方式去修改vuex中的变量数据。还是推荐使用后面的和进行变量的修改。
组件2号: {{ $store.state.data1 }}
显示效果:

Getter
Vuex 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性)。就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
const store = new Vuex.Store({
state: {
todos: [
{ id: 1, text: '...', done: true },
{ id: 2, text: '...', done: false }
]
},
getters: {
doneTodos: state => {
// 返回todos中done为true的对象
return state.todos.filter(todo => todo.done)
}
}
})
可以通过属性进行访问:
this.$store.getters.doneTodos
效果:

Mutation
更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。
mutation也可以添加参数,会接受 state 作为第一个参数。
例子:
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state, payload) {
// 变更state中的count
state.count += payload.amount;
},
}
})
组件操作:
this.$store.commit('increment', { amount: 3 })
效果:

Action
Action 类似于 mutation,不同在于:
例子:
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
actions: {
increment (context) {
context.commit('increment')
}
}
})
组件中触发action,Action 通过 store.dispatch 方法触发
this.$store.dispatch('increment')
mutation 必须同步执行这个限制么。Action 内部可以执行异步操作
actions: {
incrementAsync ({ commit }, payload) {
setTimeout(() => {
commit('increment', payload)
}, 1000)
},
}
Module
module就是模块化,由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。
Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割。
const moduleA = {
state: () => ({ ... }),
mutations: { ... },
actions: { ... },
getters: { ... }
}
const moduleB = {
state: () => ({ ... }),
mutations: { ... },
actions: { ... }
}
创建好模块后,就可以使用module将之前的模块加载入vuex当中了
const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})
在组件中查看模块状态
this.$store.state.a // -> moduleA 的状态
this.$store.state.b // -> moduleB 的状态
以上就是快速学一遍后vuex可以掌握的基础功能和原理简述了,当然其中还有挺多其他内容的,就需要慢慢一点点在使用过程当中进行挖掘了
