vuex是什么?
专门为vue设计的状态管理架构,统一管理和维护vue的可变状态。
vuex的五个核心属性?
五个核心概念:state、getters、actions、mutations、modules
state
state是vuex的基本数据
由于vuex状态存储是响应式的,所以vue组件从store中获取状态最简单的方法就是写在计算属性中
通过在根实例中注册 store 选项,该 store 实例会注入到根组件下的所有子组件中,且子组件能通过 this.$store 访问到
const Counter = { template: `<div>{{ count }}</div>`, computed: { count () {
return this.$store.state.count } } }
mapState辅助函数
当一个组件需要获取多个状态时候,将这些状态都声明为计算属性会有些重复和冗余。为了解决这个问题,我们可以使用 mapState
辅助函数帮助我们生成计算属性,让你少按几次键。
// 在单独构建的版本中辅助函数为 Vuex.mapState import { mapState } from 'vuex' export default
{ // ... computed: mapState({ // 箭头函数可使代码更简练 count: state => state.count, //
传字符串参数 'count' 等同于 `state => state.count` countAlias: 'count', // 为了能够使用 `this`
获取局部状态,必须使用常规函数 countPlusLocalState (state) { return state.count +
this.localCount } }) } //使用对象展开符 ...mapState({ topNav: state =>
state.topNav.data, //将 this.topNav 映射为 this.$store.topNav.data navigationInfo:
state => state.topNav.navigationInfo }),
Getters
Vuex 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性)。就像计算属性一样,getter
的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
getters接收state作为其第一个参数,接受其他 getters 作为第二个参数,如不需要,第二个参数可以省略如下例子:
const store = new Vuex.Store({ state: { count:0 }, getters: { // 单个参数
countDouble: function(state){ return state.count * 2 }, // 两个参数
countDoubleAndDouble: function(state, getters) { return getters.countDouble * 2
} } })
通过属性访问
Getter 会暴露为 store.getters 对象,你可以以属性的形式访问这些值:
store.getters.doneTodos // -> [{ id: 1, text: '...', done: true }]
通过方法访问
getters: { // ... getTodoById: (state) => (id) => { return
state.todos.find(todo => todo.id === id) } } //通过方法访问
store.getters.getTodoById(2) // -> { id: 2, text: '...', done: false }
mapGetters 辅助函数仅仅是将 store 中的 getter 映射到局部计算属性:
import { mapGetters } from 'vuex' export default { // ... computed: { //
使用对象展开运算符将 getter 混入 computed 对象中 ...mapGetters([ 'doneTodosCount',
'anotherGetter', // ... ]) } } mapGetters({ // 把 `this.doneCount` 映射为
`this.$store.getters.doneTodosCount` doneCount: 'doneTodosCount' })
Mutation
更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。
mutation必须是同步的,如果要异步需要使用action。
每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数
(handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state
作为第一个参数,提交载荷作为第二个参数。(提交荷载在大多数情况下应该是一个对象),提交荷载也可以省略的。
const store = new Vuex.Store({ state: { count: 1 }, mutations: { //无提交荷载
increment(state) { state.count++ } //提交荷载 incrementN(state, obj) { state.count
+= obj.n } } }) //组件中调用 //无提交荷载 store.commit('increment') //提交荷载
store.commit('incrementN', { n: 100 })
mapMutations 辅助函数
import { mapMutations } from 'vuex' export default { //.. methods: {
...mapMutations([ 'increment' // 映射 this.increment() 为
this.$store.commit('increment') ]), ...mapMutations({ add: 'increment' // 映射
this.add() 为 this.$store.commit('increment') }) } }
Action
Action 类似于 mutation,不同在于:
* Action 提交的是 mutation,而不是直接变更状态。
* Action 可以包含任意异步操作。 const store = new Vuex.Store({ state: { count: 0 },
mutations: { increment (state) { state.count++ } }, actions: { increment
(context) { context.commit('increment') } } })
注意:Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个
mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters。
Action 通过 store.dispatch 方法触发:
store.dispatch('increment')
mapActions辅助函数
你在组件中使用 this.$store.dispatch('xxx') 分发 action,或者使用 mapActions 辅助函数将组件的 methods
映射为 store.dispatch 调用(需要先在根节点注入 store):
import { mapActions } from 'vuex' export default { //.. methods: {
...mapActions([ 'incrementN' //映射 this.incrementN() 为
this.$store.dispatch('incrementN') ]), ...mapActions({ add: 'incrementN' //映射
this.add() 为 this.$store.dispatch('incrementN') }) } }
Module
使用单一状态树,导致应用的所有状态集中到一个很大的对象。但是,当应用变得很大时,store 对象会变得臃肿不堪。
为了解决以上问题,Vuex 允许我们将 store 分割到模块(module)。每个模块拥有自己的
state、mutation、action、getters、甚至是嵌套子模块——从上至下进行类似的分割:
import Vuex from 'vuex'; import topNav_store from "./topNav/store.js"; import
member_store from "./member/store.js"; import game_store from
"./coupon/game.js"; import approval from './approval/store.js' import
setRentInfo from './contract/store.js' export default new Vuex.Store({
modules:{ topNav:topNav_store, memberStore:member_store, game_store:game_store,
approval:approval, setRentInfo } })