Vuex:https://v3.vuex.vuejs.org/zh
什么是状态管理器?方便调试,方便维护数据。https://vuex.vuejs.org/zh/#什么是“状态管理模式”?
Vuex使用记录
1.在Vue2.x中使用
代码语言:javascript复制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中使用
代码语言:javascript复制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模块之后,辅助函数的用法将产生改变
代码语言:javascript复制 ...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 辅助函数帮助我们生成计算属性,如:
代码语言:javascript复制computed: mapState([
/*映射 this.count 为 store.state.count*/
'count'
])
mapState返回的是一个包含各种计算属性的对象,可以使用...对象展开运算符抽取出来,成为多个单独的计算属性。
6.getter(state的计算属性?)
从 Vue 3.0 开始,getter 的结果不再像计算属性一样会被缓存起来。这是一个已知的问题,将会在 3.2 版本中修复。
代码语言:javascript复制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 方法:
代码语言:javascript复制store.commit('increment')
载荷(Payload),可以向 store.commit
传入额外的参数,即 mutation 的载荷(payload),载荷应该是一个对象,这样可以包含多个字段并且记录的 mutation 会更易读。
一条重要的原则就是要记住 mutation 必须是同步函数。为什么:https://vuex.vuejs.org/zh/guide/mutations.html#mutation-必须是同步函数
同样的mapMutations 辅助函数可以将 store 中的 mutations 映射到局部计算属性:
代码语言:javascript复制...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对象上需要的方法直接做为参数)
代码语言:javascript复制actions: {
increment ({ commit }) {
commit('increment')
}
}
代码语言:javascript复制/* 参数解构 */
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#组合-action
9.模块分割 Module
Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割:(通过modules属性进行注册)
代码语言:javascript复制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 函数,当不再需要订阅时,应调用该函数。
官方文档:https://vuex.vuejs.org/zh/api/index.html#subscribe