Vuex状态管理器
上庸往事 人气:0一、Vuex是什么?
Vuex在Vue项目开发时使用的状态管理工具。简单来说,就是对Vue的应用中多个组件的共享状态进行集中式的管理(读/写)
Vuex实现了一个单向数据流,在全局拥有一个State存放数据,当组件要更改State中的数据时,必须通过Mutation进行,Mutation同时提供了订阅者模式供外部插件调用获取State数据的更新。
而当所有异步操作(常见于调用后端接口异步获取更新数据)或批量的同步操作需要走Action,但Action也是无法直接修改State的,还是需要通过Mutation来修改State的数据。最后,根据State的变化,渲染到视图上。
二、什么时候使用Vuex
不适用场景:小型简单应用,用 Vuex 是繁琐冗余的,更适合使用简单的store模式
适用场景:构建一个中大型单页应用,可能会考虑如何更好地在组件外部管理状态,即多个组件共享状态:
多个视图依赖于同一状态:此时传参的方法对于多层嵌套的组件将会非常繁琐,并且对于兄弟组件间的状态传递无能为力。
来自不同视图的行为需要变更同一状态:此时采用父子组件直接引用或者通过事件来变更和同步状态的多份拷贝,通常会导致无法维护的代码
在这些情况下就适合用Vuex进行全局单例模式管理
三、Vuex的核心概念和API
流程:View -> Actions -> Mutations -> State -> View
1、state
1) vuex 管理的状态对象
2) 它应该是唯一的
const state = { xxx: initValue }
2、 mutations
1) 包含多个直接更新 state 的方法(回调函数)的对象
2) 谁来触发: action 中的 commit('mutation 名称')或者在组件中通过this.$store.commit(‘xxx’,params)使用。这个和组件中的自定义事件类似
3) 只能包含同步的代码, 不能写异步代码
const mutations = { xxx(state, {data1}) { // 更新 state 的某个属性 } }
3、 actions
1) 提交 mutation,异步操作。包含多个事件回调函数的
2) 通过执行: commit()来触发 mutation 的调用, 间接更新 state
3) 谁来触发: 组件中通过this.$store.dispatch('action 名称', data1)
4) 可以包含异步代码(axios)
const actions ={ zzz ({commit, state}, data1){ commit('xxx', {data1}) } }
4、 getters
1) 对数据获取之前的再次编译,可以理解为state的计算属性
2) 谁来读取: 组件中: this.$store.getters.xxx
const getters ={ xxx(state) { return ... } }
5、 modules
1) 包含多个 module:store的子模块,为了开发大型项目,方便状态管理而使用的,即将store分割为模块,使store对象不会太臃肿。
2)一个 module 是一个 store 的配置对象
3) 与一个组件(包含有共享数据)对应
四、应用举例
1、安装:npm i vuex -S
2、创建store:src/store/index.js
import { createStore} from "vuex"; export default createStore({ //vuex中的数据源,我们需要保存的数据就保存在这里,可以在组件通过 this.$store.state来获取我们定义的数据; state: { count: 0, age: 0 }, /* (1)Getter相当于vue中的computed计算属性,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算 (2)通过属性访问Getter会暴露为 store.getters 对象,可以以属性的形式访问这些值:this.$store.getters.xxx (3)Getters 可以用于监听state中的值的变化,返回计算后的结果 */ getters: { getterAge(state){ return state.age =25 } }, /* 更改 Vuex 的 store 中的状态的唯一方法是提交 mutation,并且Mutation 必须是同步函数 在sotre.js中定义mutations对象,该对象中有两个方法,mutations里面的参数,第一个默认为state, 其中第二个参数obj在官方文档就是载荷(payload),可以传入参数及对象。 在大多数情况下,载荷应该是一个对象,这样可以包含多个字段并且记录的 mutation 会更易读 */ mutations: { addCount(state,obj){ return state.count += obj.num }, subCount(state,obj){ return state.count -= obj.num } }, actions: { addCountAsyn(context){ setTimeout(()=>{ context.commit('addCount',{ num: 1 }) },3000) }, subCountAsyn(context){ setTimeout(()=> { context.commit('subCount',{ num: 1 }) },2000) } } })
3、在main.js文件中使用store
4、创建Home.vue组件
<template> <div> <h2>通过getter获得计算后的年龄:{{ getterAge }}</h2> <p>Count:{{ count }}</p> <button @click="handlerAdd()">加1</button> <button @click="handlerSub()">减1</button> <button @click="handlerAddAnys()">异步增加(2s后执行)</button> <button @click="handlerSubAnys()">异步减少(2s后执行)</button> </div> </template> <script> export default { name: "Home", computed: { count(){ return this.$store.state.count }, getterAge(){ return this.$store.getters.getterAge } }, methods: { handlerAdd(){ this.$store.commit("addCount",{ num: 1 }) }, handlerSub(){ this.$store.commit("subCount",{ num: 1 }) }, handlerAddAnys(){ this.$store.dispatch('addCountAsyn') }, handlerSubAnys(){ this.$store.dispatch('subCountAsyn') } } } </script>
6、在App.vue中导入Home.vue
7、运行效果:
五、vuex中各种辅助函数的用法,可以使我们更加方便的运用vuex
1、…mapState
count(){ return this.$store.state.count },
等价于
...mapState([ 'count' ]),
2、…mapGetters
getterAge(){ return this.$store.getters.getterAge }
等价于
...mapGetters(['getterAge'])
3、…mapMutations:使用辅助函数后载荷的传参,直接在调用的地方进行传参便可
handlerAdd(){ this.$store.commit("addCount",{ num: 1 }) }, handlerSub(){ this.$store.commit("subCount",{ num: 1 }) },
等价于
...mapMutations({ handlerAdd: 'addCount', handlerSub: 'subCount' })
4、…mapActions
handlerAddAnys(){ this.$store.dispatch('addCountAsyn') }, handlerSubAnys(){ this.$store.dispatch('subCountAsyn') }
等价于
...mapActions({ handlerAddAnys: 'addCountAsyn', handlerSubAnys: 'subCountAsyn' })
修改上例中的Home.vue组件
加载全部内容