Vuex 使用单一状态树
一个对象就包含了全部的应用层级状态
作为一个“唯一数据源 ”而存在
每个应用将仅仅包含一个 store 实例
单状态树和模块化并不冲突
如何将状态和状态变更事件分布到各个子模块中?
在 Vue 组件中获得 Vuex 状态
从 store 实例中读取状态最简单的方法就是在计算属性中返回某个状态:
store.state.count 组件中 this.$store.state.count;
// 创建一个 Counter 组件 const Counter = { template: `<div>{{ count }}</div>`, computed: { count () { return store.state.count //组件中 this.$store.state.count; } } }
每当 store.state.count
变化的时候, 都会重新求取计算属性,并且触发更新相关联的 DOM。
在模块化的构建系统中,在每个需要使用 state 的组件中需要频繁地导入,并且在测试组件时需要模拟状态
Vuex 通过 store
选项 (调用 Vue.use(Vuex)
) 将状态从根组件“注入”到每一个子组件中。
const Counter = { template: `<div>{{ count }}</div>`, computed: { count () {
//当下面的store 实例注入到根组件下的所有子组件中后,子组件通过this.$store
访问到 return this.$store.state.count } } }
const app = new Vue({ el: '#app', // 把 store 对象提供给 “store” 选项,这可以把 store 的实例注入所有的子组件 store, components: { Counter }, template: ` <div class="app"> <counter></counter> </div> ` })
mapState
辅助函数
使用 mapState
辅助函数,可以帮助我们生成计算属性。
当一个组件需要获取多个状态的时候,可以将这些状态使用mapState
声明为计算属性。
index.js:
import Vue from 'vue'; import 'es6-promise/auto' import Vuex from 'vuex'; Vue.use(Vuex); const store = new Vuex.Store({ state: { count: 0, countPlus: 1, countLength: 1, }, mutations: { increment(state) { state.count++; state.countPlus = state.count + 1; state.countLength = state.count.toString().length; }, decrement(state) { state.count--; state.countPlus = state.count + 1; state.countLength = state.count.toString().length; }, }, }); export default store;
StoreComponent.vue:
<template> <div> <button @click="increment"> {{count}}</button> <button @click="decrement"> {{count}}</button> <span> Plus one: {{ countPlus }}</span> <span> Length: {{ countLength}}</span> </div> </template> <script> import {mapState} from 'vuex'; export default { name: "StoreComponent", // computed: { // count() { // return this.$store.state.count; // }, // // }, computed: mapState({ count: state => state.count, countPlus: 'countPlus', countLength(state) { return state.countLength; }, }), // computed: mapState({ // // count: state => state.count, // // count: 'count', // }), // computed: mapState([ // 'count', // 'countPlus', // 'countLength', // ]), methods: { increment() { this.$store.commit('increment'); }, decrement() { this.$store.commit('decrement'); }, } } </script> <style scoped> </style>
除了:
computed: mapState({ count: state => state.count, countPlus: 'countPlus', countLength(state) { return state.countLength; }, }),
也可以使用:
computed: mapState([ 'count', 'countPlus', 'countLength', ]),
对象展开运算符
mapState
函数返回的是一个对象
像这样:
//这样的我们怎么添加其他本地计算属性呢? computed: mapState({ count: state => state.count, countPlus: 'countPlus', countLength(state) { return state.countLength; }, }),
方法:使用对象展开运算符
即:
computed: {
localComputed () { /* ... */ },
// 使用对象展开运算符将此对象混入到外部对象中
...mapState({//三个点必须要
// ...
})
}
computed: { countPlusLength() { return this.countPlus.toString().length; }, ...mapState({ count: state => state.count, countPlus: 'countPlus', countLength(state) { return state.countLength; }, }) },
注意:
使用 Vuex 并不意味着你需要将所有的状态放入 Vuex。
虽然将所有的状态放到 Vuex 会使状态变化更显式和易调试,但也会使代码变得冗长和不直观。
如果有些状态严格属于单个组件,最好还是作为组件的局部状态。
你应该根据你的应用开发需要进行权衡和确定。