首先需要去官网熟悉一下基本概念。Vuex 是集中式状态管理工具。它和全局对象有两点区别,第一点是 Vuex 中的数据是响应式的,即数据变动视图也会跟着变动,第二点是 Vuex 中的数据必须显示提交才可以改变,也就是说修改数据的时候都需要显示调用提供的 commit 方法。它的核心概念有4个,其中 state 用来存放数据,getter 用来获取数据(类似于 Vue 的计算属性),mutation 用来修改数据(这个是修改数据的唯一方法),action 用来异步修改数据(注意,它需要通过 mutation 修改数据)
Vuex 作为全局管理插件,需要实现跨多个组件通信的场景,所以需要使用 provide/inject 方法。Vue 和 Vuex 链接是通过插件进行的,Vuex 在实现的时候需要有 install 方法,而 Vue 通过 use 方法调用插件中的 install 方法。
该模块引入 inject,reactive,computed 三个方法,其中 inject 用于跨组件使用对象,这里获取到的是 new store 后生成的实例;reactive 用于将 state 中的数据变成响应式的;computed 用于 getter 获取 state 中的数据并保持响应式。
该模块输出 useStore 和 createStore 两个方法,其中 createStore 方法可以将参数中的 state 变成响应式的,getters 响应式获取 state 中的数据并且支持多个方法,另外还支持 commit 和 dispath
commit 方法会直接存在于 new Store 创建的实例中,这个不同于 dispatch 方法,它只存在于 Store 的实例对象中,这个是实例属性的新写法,可以参考 ES6入门
- import { inject, reactive, computed } from "vue";
-
- const STORE_KEY = "__store__";
-
- // 组件中使用的时候调用
- function useStore() {
- return inject(STORE_KEY);
- }
-
- // 使用 app.use 方法的时候调用
- function createStore(options) {
- return new Store(options);
- }
-
- class Store {
- constructor(options) {
- this.$options = options;
- this._state = reactive({
- data: options.state(),
- });
- this._mutations = options.mutations;
- this._actions = options.actions;
- this.getters = {};
-
- // 遍历 options.getters 中的所有方法,然后放到 getters 中并使用 computed 方法保持响应性
- Object.keys(options.getters).forEach((name) => {
- const fn = options.getters[name];
- this.getters[name] = computed(() => fn(this.state));
- });
- }
- // store.state 的时候获取 data
- get state() {
- return this._state.data;
- }
- // 如果有对应的方法,则调用该方法
- commit = (type, payload) => {
- const entry = this._mutations[type];
- entry && entry(this.state, payload);
- };
- dispatch(type, payload) {
- const entry = this._actions[type];
- return entry && entry(this, payload);
- }
- install(app) {
- app.provide(STORE_KEY, this);
- }
- }
- export { createStore, useStore };
- 复制代码
通过学习手写 Vuex 的代码可以加深对官网文档的理解,同时注意平常使用的时候需要保持响应性,并且只通过 commit 方法进行显示修改数据。