Vuex3.x、Vuex4.x状态管理器学习笔记
- Vue学习
- 2022-02-08
- 1055热度
- 0评论
Vuex:https://v3.vuex.vuejs.org/zh
什么是状态管理器?方便调试,方便维护数据。https://vuex.vuejs.org/zh/#%E4%BB%80%E4%B9%88%E6%98%AF%E2%80%9C%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86%E6%A8%A1%E5%BC%8F%E2%80%9D%EF%BC%9F
Vuex使用记录
1.在Vue2.x中使用
import Vuex from 'vuex' /* 引入Vuex */
Vue.use(Vuex) /* 安装插件 */
/* 实例化Vuex */
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
}
})
/* 挂载到所有组件 */
new Vue({
el: '#app',
store: store,
})
2.在Vue3.x中使用
import { createApp } from 'vue'
import { createStore } from 'vuex'
/* 创建一个新的 store 实例 */
const store = createStore({
state () {
return {
count: 0
}
},
mutations: {
increment (state) {
state.count++
}
}
})
const app = createApp({ /* 根组件 */ })
/* 将 store 实例作为插件安装 */
app.use(store)
3.辅助函数
mapState、mapGetters、mapActions、mapMutations
- 当映射的计算属性的名称与 state 的子节点名称相同时,我们也可以给 辅助函数 传一个字符串数组。使用不用的名字时传入一个对象
- mapMutation 转换为对应的 this.$store.commit("mutations")
- mapActions转换为this.$store.dispatch('action')
- 在setup中通过useStore()获取store对象实例。无法使用辅助函数
- 当vuex使用了module模块之后,辅助函数的用法将产生改变
...mapActions([ 'some/nested/module/foo', /* -> this['some/nested/module/foo']()*/ 'some/nested/module/bar' /*-> this['some/nested/module/bar']()*/ ]) /* 可以在第一个参数中传递模块名,简写 */ ...mapActions('some/nested/module', [ 'foo', /* -> this.foo() */ 'bar' /* -> this.bar()*/ ])
4.学习
- Vuex 使用单一状态树——是的,用一个对象就包含了全部的应用层级状态。至此它便作为一个“唯一数据源 (SSOT)”而存在。
- Vuex的对象可以用过use注入vue应用,成为所有组件的store属性。也可以单独引入这个对象,单独使用。
- Vuex的所有方法中,this指向Vuex对象。
5.state(状态/数据)
- 由于 Vuex 的状态存储是响应式的,从 store 实例中读取状态最简单的方法就是在计算属性中返回某个状态,每当 store.state.count 变化的时候, 都会重新求取计算属性,并且触发更新相关联的 DOM。
- 当一个组件需要获取多个状态的时候,将这些状态都声明为计算属性会有些重复和冗余。为了解决这个问题,我们可以使用 mapState 辅助函数帮助我们生成计算属性,如:
computed: mapState([ /*映射 this.count 为 store.state.count*/ 'count' ])
mapState返回的是一个包含各种计算属性的对象,可以使用...对象展开运算符抽取出来,成为多个单独的计算属性。
6.getter(state的计算属性?)
- 从 Vue 3.0 开始,getter 的结果不再像计算属性一样会被缓存起来。这是一个已知的问题,将会在 3.2 版本中修复。
getters: { doneTodos: (state) => { return state.todos.filter(todo => todo.done) } }
Getter 会暴露为
store.getters
对象,你可以以属性的形式访问这些值。Getter 也可以接受其他 getter 作为第二个参数。 - 同样的mapGetters 辅助函数可以将 store 中的 getter 映射到局部计算属性:
7.mutation(事件,由commit触发)
- 更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的事件类型 (type)和一个回调函数 (handler)。
- 不能直接调用一个 mutation 处理函数,要唤醒一个 mutation 处理函数,你需要以相应的 type 调用 store.commit 方法:
store.commit('increment')
- 载荷(Payload),可以向
store.commit
传入额外的参数,即 mutation 的载荷(payload),载荷应该是一个对象,这样可以包含多个字段并且记录的 mutation 会更易读。 - 一条重要的原则就是要记住 mutation 必须是同步函数。为什么:https://vuex.vuejs.org/zh/guide/mutations.html#mutation-%E5%BF%85%E9%A1%BB%E6%98%AF%E5%90%8C%E6%AD%A5%E5%87%BD%E6%95%B0
- 同样的mapMutations 辅助函数可以将 store 中的 mutations 映射到局部计算属性:
...mapMutations({ add: 'increment' /*将 `this.add()` 映射为 `this.$store.commit('increment')`*/ })
8.action(异步处理状态,由dispatch触发)
- Action 提交的是 mutation,而不是直接变更状态。Action 可以包含任意异步操作。
- Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters。(通过参数解构拉取context对象上需要的方法直接做为参数)
actions: { increment ({ commit }) { commit('increment') } }
/* 参数解构 */ actions: { checkout ({ commit, state }, products) { } }
- Actions 支持同样的载荷方式和对象方式进行分发(dispatch(action,param))。
- 同样的mapActions 辅助函数可以将 store 中的 action 映射到局部计算属性。
store.dispatch
可以处理被触发的 action 的处理函数返回的 Promise,并且store.dispatch
仍旧返回 Promise。- 组合action:https://vuex.vuejs.org/zh/guide/actions.html#%E7%BB%84%E5%90%88-action
9.模块分割 Module
- Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割:(通过modules属性进行注册)
const moduleA = { state: () => ({ ... }), mutations: { ... }, actions: { ... }, getters: { ... } } const moduleB = { state: () => ({ ... }), mutations: { ... }, actions: { ... } } const store = createStore({ modules: { a: moduleA, b: moduleB } }) store.state.a /* -> moduleA 的状态 */ store.state.b /* -> moduleB 的状态 */
- 对于模块内部的 mutation 和 getter,接收的第一个参数是模块的局部状态对象。
- 对于模块内部的 action,局部状态通过 context.state 暴露出来,根节点状态则为 context.rootState。
细节总结
- 默认情况下,模块内部的 action 和 mutation 仍然是注册在全局命名空间(在Vuex对象上面,而不是模块对象)的——这样使得多个模块能够对同一个 action 或 mutation 作出响应。Getter 同样也默认注册在全局命名空间。
- 可以通过添加 namespaced: true 的方式使其成为带命名空间的模块。当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名。
- 模块的动态注册和卸载:store.registerModule、store.unregisterModule()(无法卸载声明时的模块)
- 类似data属性,有时为了模块重用,如果我们使用一个纯对象来声明模块的状态,那么这个状态对象会通过引用被共享,导致状态对象被修改时 store 或模块间数据互相污染的问题
10.项目结构说明
官方文档:https://vuex.vuejs.org/zh/guide/structure.html
11.组合式API使用
- 可以通过调用 useStore 函数,来在 setup 钩子函数中访问 store。这与在组件中使用选项式 API 访问
this.$store
是等效的。 - 官方文档:https://vuex.vuejs.org/zh/guide/composition-api.html
- 在其他文件中使用状态管理器时,直接引入创建好的store对象即可。
12.订阅
订阅 store 的 mutation。handler 会在每个 mutation 完成后调用,接收 mutation 和经过 mutation 后的状态作为参数
订阅 store 的 action。handler 会在每个 action 分发的时候调用并接收 action 描述和当前的 store 的 state 这两个参数。 subscribe 方法将返回一个 unsubscribe 函数,当不再需要订阅时,应调用该函数。