手写 Vuex 4.x

176 阅读5分钟
Vue 3.0 系列文章

Vue 3.0组件的渲染流程

Vue 3.0组件的更新流程和diff算法详解

揭开Vue3.0 setup函数的神秘面纱

Vue 3.0 Props的初始化和更新流程的细节分析

Vue3.0 响应式实现原理分析

Vue 3.0 计算属性的实现原理分析

Vue3.0 常用响应式API的使用和原理分析(一)

Vue3.0 常用响应式API的使用和原理分析(二)

Vue 3.0 Provide和Inject实现共享数据

Vue 3.0 Teleport的使用和原理分析

Vue3侦听器和异步任务调度, 其中有个神秘角色

Vue3.0 指令

Vue3.0 内置指令的底层细节分析

Vue3.0 的事件绑定的实现逻辑是什么

Vue3.0 的双向绑定是如何实现的

Vue3.0的插槽是如何实现的?

探究Vue3.0的keep-alive和动态组件的实现逻辑

Vuex 4.x

Vue Router 4 的使用,一篇文章给你讲透彻

Vuex是官方提供的状态管理库,为了深入了解它的实现逻辑,本文我们一起来一步步实现它。

初始化

用法
// 1. 引入createStore函数
import { createStore } from "vuex";

// 2. 通过创建一个新的 store 实例
const store = createStore({

});

// 3. 将 store 实例作为插件安装
createApp(App).use(store).mount('#app')

代码实现
// 创建一个生成Store的
export function createStore() {
  return new Store();
}

// 把所有的功能放在 Store 实例中
export class Store {
  
  constructor() {}

  // 能做为插件,会调用install方法
  install(app, ...options) {
    
  }
}

state

用法
const store = createStore({
  // 1. 传入state
  state: {
    count: 2,
  }
});
<!-- 使用的组件 -->
<template>
  <div>
    <!-- 5. 模板中使用 -->
    {{ count }}
    <!-- 或者 -->
    {{ $store.state.count }}
  </div>
</template>

<script lang="ts">
import { defineComponent } from "vue";
// 2. 引入useStore函数
import { useStore } from 'vuex';

export default defineComponent({
  name: "App",
  setup() {

    // 3. 获取store
    const store = useStore();

    return {
      // 4. 响应式的count
      count: computed(() => store.state.count),
    };
  },
});
</script>
代码实现

思路:

  1. 通过Provide/Inject的技术实现每个组件能够通过useStore方法获取到store实例;
  2. 可以将store实例挂载到app.config.globalProperties.$store上,这样通过$store也可以取到store实例;
  3. state数据应该封装成响应式;
// 定一个key, 作为 provide/inject 的 key
const storeKey = "store";

export function createStore(options) {
  return new Store(options);
}

export class Store {
  
  constructor(options) {
    let _this = this;
    
    // 取到state并且变成响应式的数据, 加data这次是修改state方便
    this._state = reactive({data: options.state || Object.create(null)});

  }

  // 属性访问器进行数据封装,取的是_state.data
  get state() {
    return this._state.data;
  }

  install(app, ...options) {
    
    // 通过Provide注入给所有组件
    app.provide(storeKey, this);

    // 挂载在全局对象上,可通过this.$store取到
    app.config.globalProperties.$store = this;

  }

}

// 返回注入的store对象
export function useStore() {
  return inject(storeKey);
}

getters

用法
export default createStore({
  getters: {
    plusOne: (state) => state.count + 1,
  }
});
<template>
  <div>
    <!-- 使用数据 -->
    {{ plusOne }}
    {{ $store.getters.plusOne }}
  </div>
</template>

<script lang="ts">
import { computed, defineComponent } from "vue";
import { useStore } from "vuex";

export default defineComponent({
  name: "App",
  setup() {

    const store = useStore();

    return {
      // 获取 getter 数据
      plusOne: computed(() => store.getters.plusOne),
    };
  }
});
</script>
代码实现

思路: 使用的时候是用属性取值,而定义的时候是函数,所以需要将 函数调用 变成 获取属性

export class Store {
  
  constructor(options) {
    
    // 将getters函数转成属性
    this.getters = {};
    // this.getters = {plusOne: }
    foreachValue(options.getters, (value, key) => {
      // value 是 一个函数
      Object.defineProperty(this.getters, key, {
        // getters 都是基于 state, 所以传入this.state
        // 获取值的时候本质上还是函数调用
        get: () => value(_this.state)
      })
    });

  }

}
  • 工具函数
/**
 * 遍历对象属性执行函数
 * @param {*} obj 需要遍历的对象
 * @param {*} fn 对象的每个key值, 执行函数,传参为 value 和 key
 */
export function foreachValue(obj, fn) {
  if (isObject(obj)) {
    Object.keys(obj).forEach(key => fn(obj[key], key));
  }
}

/**
 *
 * @param {*} obj 传入参数
 * @returns 是否是对象
 */
export function isObject (obj) {
  return obj !== null && typeof obj === 'object'
}

mutation

用法
export default createStore({
  mutations: {
    increment(state, n) {
      state.count += n;
    },
  },
});
<template>
  <div>
    <!-- 使用increment -->
    <button @click="increment">增加计数</button>
  </div>
</template>

<script lang="ts">
import { computed, defineComponent } from "vue";
import { useStore } from "vuex";

export default defineComponent({
  name: "App",
  setup() {

    const store = useStore();

    let increment = () => {
      // 调用 store 的 increment 方法,传参5
      store.commit("increment", 5);
    }

    return {
      increment,
    };
  }
});
</script>
代码实现

思路: 将所有的mutations放置在_mutations对象容器中{'方法名': 函数实现 }, store.commit调用的时候直接从_mutations对象容器中获取到对应的函数并且执行

export class Store {
  
  constructor(options) {

    // 创建一个_mutation容器
    this._mutations = Object.create(null);
    foreachValue(options.mutations, (mutation, key) => {
      this._mutations[key] = (payload) => {
        // 将this重新指向为实例对象store,可以接收两个参数,state和payload
        mutation.call(this, this.state, payload);
      };
    });

  }

  // 提交mutation的函数
  commit = (methodName, payload) => {
    // 从_mutation对象容器中找对应的函数
    let fn = this._mutations[methodName];
    if (fn) {
      // 执行fn, 传payload
      fn(payload);
    }
  }

}

Action

用法
export default createStore({
  actions: {
    <!-- action和mutation的第一个参数有较大区别 -->
    incrementAsync ({ commit }, payload) {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          commit('increment', payload)
          resolve()
        }, 1000)
      })
    }
  }
});
<template>
  <div>
    <!-- 调用异步计数 -->
    <button @click="incrementAsync">异步计数</button>
  </div>
</template>

<script lang="ts">
import { computed, defineComponent } from "vue";
import { useStore } from "vuex";

export default defineComponent({
  name: "App",
  setup() {
    const store = useStore();

    let incrementAsync = () => {
      <!-- dispatch 异步调用, 返回一个Promise对象 -->
      store.dispatch("incrementAsync", 10);
    };
    
    return {
      incrementAsync,
    };
  },
});
</script>

代码实现

思路: 所有的actions放置在_actions对象容器中{'方法名': 函数实现 }, store.dispatch调用的时候直接从_actions对象容器中获取到对应的函数并且执行

异步的操作需要用到Promise

export class Store {
  
  constructor(options) {

    this._actions = Object.create(null);
    // 遍历所有的actions函数 
    foreachValue(options.actions, (action, key) => {
      this._actions[key] = (payload) => {
        // 调用函数, 将一些上下文传递,因为 异步的操作 不仅是操作 state, 还可能需要操作commit,getters,dispatch等。
        let res = action.call(this, {
          dispatch: this.dispatch,
          commit: this.commit,
          getters: this.getters,
          state: this.state,
        }, payload);
        // 函数可能是异步也可能是同步, 如果同步则通过`Promise.resolve`将函数结果转为成功的Promise
        if (!isPromise(res)) {
          res = Promise.resolve(res);
        }
        return res;
      }
    })

  }

  dispatch = (methodName, payload) => {
    let fn = this._actions[methodName];
    if (fn) {
      let result = fn(payload);
      // 返回一个Promise对象,它的状态和结果由result决定
      return new Promise((resolve, reject) => {
        result.then(
          (res) => {
            resolve(res);
          },
          (error) => {
            reject(error);
          }
        );
      });
    }
  }

}

/**
 * 
 * @param {*} val 传入的参数
 * @returns 是否是Promise对象
 */
export function isPromise (val) {
  return val && typeof val.then === 'function'
}

版本一完成

至此,四部分功能都已经实现了,包括state, getters, mutaions, actions

全部代码如下:

import { reactive } from 'vue';

const storeKey = "store";

export function createStore(options) {
  return new Store(options);
}

export class Store {
  
  constructor(options) {

    this._state = reactive({data: options.state || Object.create(null)});
    
    this.getters = {};
    foreachValue(options.getters, (value, key) => {
      Object.defineProperty(this.getters, key, {
        get: () => value(this.state)
      })
    });

    this._mutations = Object.create(null);
    foreachValue(options.mutations, (mutation, key) => {
      this._mutations[key] = (payload) => {
        mutation.call(this, this.state, payload);
      };
    });

    this._actions = Object.create(null);
    foreachValue(options.actions, (action, key) => {
      this._actions[key] = (payload) => {
        let res = action.call(this, {
          dispatch: this.dispatch,
          commit: this.commit,
          getters: this.getters,
          state: this.state,
        }, payload);
        if (!isPromise(res)) {
          res = Promise.resolve(res);
        }
        return res;
      }
    })

  }

  commit = (methodName, payload) => {
    let fn = this._mutations[methodName];
    if (fn) {
      fn(payload);
    }
  }

  dispatch = (methodName, payload) => {
    let fn = this._actions[methodName];
    if (fn) {
      let result = fn(payload);
      return new Promise((resolve, reject) => {
        result.then(
          (res) => {
            resolve(res);
          },
          (error) => {
            reject(error);
          }
        );
      });
    }
  }

  get state() {
    return this._state.data;
  }

  install(app, ...options) {
    
    app.provide(storeKey, this);
    app.config.globalProperties.$store = this;

  }

}

export function useStore() {
  return inject(storeKey);
}

export function foreachValue(obj, fn) {
  if (isObject(obj)) {
    Object.keys(obj).forEach(key => fn(obj[key], key));
  }
}

export function isObject (obj) {
  return obj !== null && typeof obj === 'object'
}

export function isPromise (val) {
  return val && typeof val.then === 'function'
}

modules

我们举的例子有一个子模块aModule, 子模块aModule下有一个子模块bModule

export default createStore({
  state: {
    count: 1,
  },
  getters: {
    plusOne: ...
  },
  mutations: {
    increment: ...
  },
  actions: {
    incrementAsync: ...
  },
  modules: {
    aModule: {
      state: {
        count: 1,
      },
      getters: {
        plusOneA: ...
      },
      mutations: {
        incrementA: ...
      },
      actions: {
        incrementAsyncA: ...
      },
      modules: {
        bModule: {
          state: {
            count: 1,
          },
          getters: {
            plusOneB: ...
          },
          mutations: {
            incrementB: ...
          },
          actions: {
            incrementAsyncB: ...
          }
        },
      },
    },
  },
});
代码实现
  • 首先将options参数进行格式化,方便进行后续的数据管理:

改造成:

root = {
    _rawModule: rootModule({ state, geters, mutations, actions, modules}),
    state: rootModule.state,
    _childeren: {
        aModule: {
            _rawModule: aModule({ state, geters, mutations, actions, modules}),
            state: aModule.state,
            _childeren: {
                bModule: {
                    _rawModule: bModule({ state, geters, mutations, actions, modules}),
                    state: bModule.state,
                    _childeren: {}
                }
            }
        }
    }
}

代码如下:

<!-- ModuleCollection.js -->
export default class ModuleCollection {

  constructor(rawRootModule) {
    // 这个方法是深度递归遍历的方法,从根部进行开始
    this.register([], rawRootModule, false);
  }

  /**
   * 递归进行遍历组织数据
   * @param {*} path 模块的名称的深度数组
   * @param {*} rawModule 模块对应的原始moudles数据
   */
  register(path, rawModule) {
    
    // 先将数据封装成Module,此时的_children还未赋值
    const newModule = new Module(rawModule);

    if (path.length == 0) {
      // 此时说明是根模块, 给root赋值
      this.root = newModule; // 这个对象其实就是createStore传入的options得到的数据
    } else {
      // 此时说明是子模块, 此时需要把自己赋值给父模块的_children
      // 找到父模块 , path.slice(0, -1) 是排除最后一个元素的数组(eg.  ["aModule", "bModule"] 得到的是 ["aModule"]),就是父模块的路劲
      const parent = this.get(path.slice(0, -1));
      console.log(path);
      console.log(parent);

      // 把newModule设置为父module的_children (eg. path[path.length - 1] 就是 "bModule", 值为 模块值 )
      parent.addChild(path[path.length - 1], newModule);
    }

    // 如果有 rawModule 有 moudules 属性, 则递归调用,递归调用时将子模块赋值当前newModule的_children
    if (rawModule.modules) {
      foreachValue(rawModule.modules, (rawChildModule, key) => {
        // path:遍历aModule的时候为 ["aModule"], bModule的时候 ["aModule", "bModule"]
        this.register(path.concat(key), rawChildModule);
      })
    }
  }

  /**
   * 这个方法是一步步深入找到对应的module
   * @param {*} path 模块路径数组
   * @returns 根据模块路径数组找到对应的module数据
   */
  get(path) {
    return path.reduce((module, key) => {
      return module.getChild(key);
    }, this.root);
  }

}

<!-- Module.js -->
export default class Module {
  constructor(rawModule) {
    // 存储原始的数据
    this._rawModule = rawModule;

    // 获取state
    const rawState = rawModule.state;
    this.state = (typeof rawState === "function" ? rawState() : rawState) || {};

    // _children的属性
    this._children = Object.create(null);
  }

  // 设置_children属性
  addChild(key, module) {
    this._children[key] = module;
  }

  // 获取_children属性
  getChild(key) {
    return this._children[key];
  }
}

  • 把格式化的_module进行安装,包括对state,getter,mutations,actions进行处理

改造成:

store._modules.root.state = {
    count: 1,
    aModule: {
        count: 1,
        bModule: {
            count: 1
        }
    }
}

store._wrappedGetters = {
    plusOne: fun(), 
    plusOneA: fun(), 
    plusOneB: fun()
}

store._mutations = {
    increment: [fun()],
    incrementA: [fun()],
    incrementB: [fun()],
}

store._actions = {
    incrementAsync: [fun()],
    incrementAsyncA: [fun()],
    incrementAsyncB: [fun()],
}

代码如下:

<!-- Module。js -->
export default class Module {
  // 省略其他逻辑    
    
  // 获取对应的getter函数
  forEachGetter(fn) {
    if (this._rawModule.getters) {
      foreachValue(this._rawModule.getters, fn);
    }
  }

  // 获取对应的actions函数
  forEachAction(fn) {
    if (this._rawModule.actions) {
      foreachValue(this._rawModule.actions, fn);
    }
  }

  // 获取对应的mutations函数
  forEachMutation(fn) {
    if (this._rawModule.mutations) {
      foreachValue(this._rawModule.mutations, fn);
    }
  }
}
<!-- Store.js -->
export class Store {
  constructor(options) {

    // 格式化
    this._modules = new ModuleCollection(options);
    
    // 数据初始
    this._actions = Object.create(null);
    this._mutations = Object.create(null);
    this._wrappedGetters = Object.create(null);

    // 安装: 处理
    const state = this._modules.root.state;
    installModule(this, state, [], this._modules.root);

  }

}


/**
 * 组织数据包括 state,getters, mutations, actions 的整理
 * @param {*} store store 对象
 * @param {*} rootState 根state对象
 * @param {*} path 模块路径数组(eg. ["aModule", "bModule"])
 * @param {*} module 当前的模块Module数据
 */
export function installModule(store, rootState, path, module) {
  // 是否是根,(空数组是根)
  const isRoot = !path.length;

  // ******** state 处理逻辑:********
  // 如果不是根,就将其按照树状结构挂载到根rootState上
  if (!isRoot) {
    // 和 Module类似, 将所有的state组织成树状结构
    const parentState = getNestedState(rootState, path.slice(0, -1));
    const moduleName = path[path.length - 1];
    parentState[moduleName] = module.state;
  }

  // local是指当前 module 的局部数据
  const local = {
    dispatch: store.dispatch,
    commit: store.commit,
    getters: store.getters,
  };
  Object.defineProperties(local, {
    state: {
      get: () => getNestedState(store.state, path),
    },
  });
  // 局部数据保存到module上
  module.context = local;

  // ******** getters 处理逻辑:********
  module.forEachGetter((getter, key) => {
    registerGetter(store, key, getter, local);
  });

  // ******** actions 处理逻辑:********
  module.forEachAction((action, key) => {
    registerAction(store, key, action, local);
  });

  // ******** mutations 处理逻辑:********
  module.forEachMutation((mutation, key) => {
    registerMutation(store, key, mutation, local);
  });

  // 遍历子节点
  foreachValue(module._children, (childModule, key) => {
    installModule(store, rootState, path.concat(key), childModule);
  });
}

// 获取对应模块的 state
export function getNestedState(state, path) {
  return path.reduce((state, key) => state[key], state);
}

/**
 * 将函数添加到_mutations[type]数组中
 * @param {*} store store对象
 * @param {*} type mutation的key
 * @param {*} handler mutation函数
 * @param {*} local 局部module数据
 */
function registerMutation(store, type, handler, local) {
  // _mutations[type]对应的是一个数组,但是 每个函数操作的是 局部的state数据 
  const entry = store._mutations[type] || (store._mutations[type] = []);
  entry.push(function (payload) {
    handler.call(store, local.state, payload);
  });
}

/**
 *  将函数以属性的形式添加到_wrapperdGetters上
 * @param {*} store store对象
 * @param {*} type getter的key
 * @param {*} rawGetter 
 * @param {*} local 
 * @returns 
 */
function registerGetter(store, type, getter, local) {
  store._wrappedGetters[type] = (store) => {
    return getter(
      local.state, // local state
      local.getters, // local getters
      store.state, // root state
      store.getters // root getters
    );
  };
}

/**
 * 将函数添加到_actions[type]数组中
 * @param {*} store store对象
 * @param {*} type action的key
 * @param {*} handler action的函数
 * @param {*} local 局部数据对象
 */
function registerAction(store, type, handler, local) {
  const entry = store._actions[type] || (store._actions[type] = []);
  entry.push(function wrappedActionHandler(payload) {
    let res = handler.call(
      store,
      {
        dispatch: local.dispatch,
        commit: local.commit,
        getters: local.getters,
        state: local.state,
        rootGetters: store.getters,
        rootState: store.state,
      },
      payload
    );
    if (!isPromise(res)) {
      res = Promise.resolve(res);
    }
    return res;
  });
}

  • 设置响应式数据_state和处理_wrapperdGetters中的数据
export function resetStoreState(store, state) {

  // 响应式数据 
  store._state = reactive({
    data: state,
  });

  // _wrappedGetters 转换成 getters 属性
  store.getters = {};

  const wrappedGetters = store._wrappedGetters;
  foreachValue(wrappedGetters, (fn, key) => {
    Object.defineProperty(store.getters, key, {
      get: () => fn(store),
      enumerable: true, // for local getters
    });
  });

}
export class Store {
  constructor(options) {

    // 格式化
    this._modules = new ModuleCollection(options);
    
    // 数据初始
    this._actions = Object.create(null);
    this._mutations = Object.create(null);
    this._wrappedGetters = Object.create(null);

    // 安装: 处理
    const state = this._modules.root.state;
    installModule(this, state, [], this._modules.root);

    // state 和 getter 的 逻辑
    resetStoreState(this, state);

  }

}

  • 需要修改commitdispatch方法
  commit = (methodName, payload) => {
    let funArr = this._mutations[methodName];
    if (funArr) {
      // 每个函数都执行
      funArr.forEach((fn) => {
        fn(payload);
      })      
    }
  };

  dispatch = (methodName, payload) => {
    let funArr = this._actions[methodName];
    if (funArr) {
      // 所以异步任务都执行完
      const result =
      funArr.length > 1
        ? Promise.all(funArr.map((handler) => handler(payload)))
        : funArr[0](payload);

      return new Promise((resolve, reject) => {
        result.then(
          (res) => {
            resolve(res);
          },
          (error) => {
            reject(error);
          }
        );
      });
    }
  };

版本二完成

至此,四部分功能都已经实现了,包括state, getters, mutaions, actionsmodules版本。

<!-- Module.js -->
import { foreachValue } from "../vuex";

export default class Module {
  constructor(rawModule) {
    // 存储原始的数据
    this._rawModule = rawModule;

    // 获取state
    const rawState = rawModule.state;
    this.state = (typeof rawState === "function" ? rawState() : rawState) || {};

    // _children的属性
    this._children = Object.create(null);
  }

  // 设置_children属性
  addChild(key, module) {
    this._children[key] = module;
  }

  // 获取_children属性
  getChild(key) {
    return this._children[key];
  }

  // 获取对应的getter函数
  forEachGetter(fn) {
    if (this._rawModule.getters) {
      foreachValue(this._rawModule.getters, fn);
    }
  }

  // 获取对应的actions函数
  forEachAction(fn) {
    if (this._rawModule.actions) {
      foreachValue(this._rawModule.actions, fn);
    }
  }

  // 获取对应的mutations函数
  forEachMutation(fn) {
    if (this._rawModule.mutations) {
      foreachValue(this._rawModule.mutations, fn);
    }
  }
}

<!-- ModuleCollection.js -->
import Module from "./module"
import { foreachValue } from "../vuex"

export default class ModuleCollection {

  constructor(rawRootModule) {
    // 这个方法是深度递归遍历的方法,从根部进行开始
    this.register([], rawRootModule, false);
  }

  /**
   * 递归进行遍历组织数据
   * @param {*} path 模块的名称的深度数组
   * @param {*} rawModule 模块对应的原始moudles数据
   */
  register(path, rawModule) {
    
    // 先将数据封装成Module,此时的_children还未赋值
    const newModule = new Module(rawModule);

    if (path.length == 0) {
      // 此时说明是根模块, 给root赋值
      this.root = newModule; // 这个对象其实就是createStore传入的options得到的数据
    } else {
      // 此时说明是子模块, 此时需要把自己赋值给父模块的_children
      // 找到父模块 , path.slice(0, -1) 是排除最后一个元素的数组(eg.  ["aModule", "bModule"] 得到的是 ["aModule"]),就是父模块的路劲
      const parent = this.get(path.slice(0, -1));
      console.log(path);
      console.log(parent);

      // 把newModule设置为父module的_children (eg. path[path.length - 1] 就是 "bModule", 值为 模块值 )
      parent.addChild(path[path.length - 1], newModule);
    }

    // 如果有 rawModule 有 moudules 属性, 则递归调用,递归调用时将子模块赋值当前newModule的_children
    if (rawModule.modules) {
      foreachValue(rawModule.modules, (rawChildModule, key) => {
        // path:遍历aModule的时候为 ["aModule"], bModule的时候 ["aModule", "bModule"]
        this.register(path.concat(key), rawChildModule);
      })
    }
  }

  /**
   * 这个方法是一步步深入找到对应的module
   * @param {*} path 模块路径数组
   * @returns 根据模块路径数组找到对应的module数据
   */
  get(path) {
    return path.reduce((module, key) => {
      return module.getChild(key);
    }, this.root);
  }

}
import { reactive } from "vue";
import ModuleCollection from "../vuex-mine/module/module-collection";

const storeKey = "store";

export function createStore(options) {
  return new Store(options);
}

export class Store {
  constructor(options) {

    // 格式化
    this._modules = new ModuleCollection(options);
    
    // 数据初始
    this._actions = Object.create(null);
    this._mutations = Object.create(null);
    this._wrappedGetters = Object.create(null);

    // 安装: 处理
    const state = this._modules.root.state;
    installModule(this, state, [], this._modules.root);

    // state 和 getter 的 逻辑
    resetStoreState(this, state);

  }

  commit = (methodName, payload) => {
    let funArr = this._mutations[methodName];
    if (funArr) {
      // 每个函数都执行
      funArr.forEach((fn) => {
        fn(payload);
      })      
    }
  };

  dispatch = (methodName, payload) => {
    let funArr = this._actions[methodName];
    if (funArr) {
      // 所以异步任务都执行完
      const result =
      funArr.length > 1
        ? Promise.all(funArr.map((handler) => handler(payload)))
        : funArr[0](payload);

      return new Promise((resolve, reject) => {
        result.then(
          (res) => {
            resolve(res);
          },
          (error) => {
            reject(error);
          }
        );
      });
    }
  };

  get state() {
    return this._state.data;
  }

  install(app, ...options) {
    app.provide(storeKey, this);
    app.config.globalProperties.$store = this;
  }
}

export function useStore() {
  return inject(storeKey);
}

/**
 * 组织数据包括 state,getters, mutations, actions 的整理
 * @param {*} store store 对象
 * @param {*} rootState 根state对象
 * @param {*} path 模块路径数组(eg. ["aModule", "bModule"])
 * @param {*} module 当前的模块Module数据
 */
export function installModule(store, rootState, path, module) {
  // 是否是根,(空数组是根)
  const isRoot = !path.length;

  // ******** state 处理逻辑:********
  // 如果不是根,就将其按照树状结构挂载到根rootState上
  if (!isRoot) {
    // 和 Module类似, 将所有的state组织成树状结构
    const parentState = getNestedState(rootState, path.slice(0, -1));
    const moduleName = path[path.length - 1];
    parentState[moduleName] = module.state;
  }

  // local是指当前 module 的局部数据
  const local = {
    dispatch: store.dispatch,
    commit: store.commit,
    getters: store.getters,
  };
  Object.defineProperties(local, {
    state: {
      get: () => getNestedState(store.state, path),
    },
  });
  // 局部数据保存到module上
  module.context = local;

  // ******** getters 处理逻辑:********
  module.forEachGetter((getter, key) => {
    registerGetter(store, key, getter, local);
  });

  // ******** actions 处理逻辑:********
  module.forEachAction((action, key) => {
    registerAction(store, key, action, local);
  });

  // ******** mutations 处理逻辑:********
  module.forEachMutation((mutation, key) => {
    registerMutation(store, key, mutation, local);
  });

  // 遍历子节点
  foreachValue(module._children, (childModule, key) => {
    installModule(store, rootState, path.concat(key), childModule);
  });
}

// 获取对应模块的 state
export function getNestedState(state, path) {
  return path.reduce((state, key) => state[key], state);
}

/**
 * 将函数添加到_mutations[type]数组中
 * @param {*} store store对象
 * @param {*} type mutation的key
 * @param {*} handler mutation函数
 * @param {*} local 局部module数据
 */
function registerMutation(store, type, handler, local) {
  // _mutations[type]对应的是一个数组,但是 每个函数操作的是 局部的state数据 
  const entry = store._mutations[type] || (store._mutations[type] = []);
  entry.push(function (payload) {
    handler.call(store, local.state, payload);
  });
}

/**
 *  将函数以属性的形式添加到_wrapperdGetters上
 * @param {*} store store对象
 * @param {*} type getter的key
 * @param {*} rawGetter 
 * @param {*} local 
 * @returns 
 */
function registerGetter(store, type, getter, local) {
  store._wrappedGetters[type] = (store) => {
    return getter(
      local.state, // local state
      local.getters, // local getters
      store.state, // root state
      store.getters // root getters
    );
  };
}

/**
 * 将函数添加到_actions[type]数组中
 * @param {*} store store对象
 * @param {*} type action的key
 * @param {*} handler action的函数
 * @param {*} local 局部数据对象
 */
function registerAction(store, type, handler, local) {
  const entry = store._actions[type] || (store._actions[type] = []);
  entry.push(function wrappedActionHandler(payload) {
    let res = handler.call(
      store,
      {
        dispatch: local.dispatch,
        commit: local.commit,
        getters: local.getters,
        state: local.state,
        rootGetters: store.getters,
        rootState: store.state,
      },
      payload
    );
    if (!isPromise(res)) {
      res = Promise.resolve(res);
    }
    return res;
  });
}

export function resetStoreState(store, state) {

  // 响应式数据 
  store._state = reactive({
    data: state,
  });

  // _wrappedGetters 转换成 getters 属性
  store.getters = {};

  const wrappedGetters = store._wrappedGetters;
  foreachValue(wrappedGetters, (fn, key) => {
    Object.defineProperty(store.getters, key, {
      get: () => fn(store),
      enumerable: true, // for local getters
    });
  });

}

/**
 * 遍历对象属性执行函数
 * @param {*} obj 需要遍历的对象
 * @param {*} fn 对象的每个key值, 执行函数,传参为 value 和 key
 */
export function foreachValue(obj, fn) {
  if (isObject(obj)) {
    Object.keys(obj).forEach((key) => fn(obj[key], key));
  }
}

/**
 *
 * @param {*} obj 传入参数
 * @returns 是否是对象
 */
export function isObject(obj) {
  return obj !== null && typeof obj === "object";
}

/**
 *
 * @param {*} val 传入的参数
 * @returns 是否是Promise对象
 */
export function isPromise(val) {
  return val && typeof val.then === "function";
}

本文主要是分析代码实现,源码请参阅 Vuex GitHub地址