Vue之手写 Vuex

1. 知识储备

1.1 Vuex 基础知识

首先需要去官网熟悉一下基本概念。Vuex 是集中式状态管理工具。它和全局对象有两点区别,第一点是 Vuex 中的数据是响应式的,即数据变动视图也会跟着变动,第二点是 Vuex 中的数据必须显示提交才可以改变,也就是说修改数据的时候都需要显示调用提供的 commit 方法。它的核心概念有4个,其中 state 用来存放数据,getter 用来获取数据(类似于 Vue 的计算属性),mutation 用来修改数据(这个是修改数据的唯一方法),action 用来异步修改数据(注意,它需要通过 mutation 修改数据)

1.2 Vue 基础知识

Vuex 作为全局管理插件,需要实现跨多个组件通信的场景,所以需要使用 provide/inject 方法。Vue 和 Vuex 链接是通过插件进行的,Vuex 在实现的时候需要有 install 方法,而 Vue 通过 use 方法调用插件中的 install 方法。

2. 源码分析

2.1 输入

该模块引入 inject,reactive,computed 三个方法,其中 inject 用于跨组件使用对象,这里获取到的是 new store 后生成的实例;reactive 用于将 state 中的数据变成响应式的;computed 用于 getter 获取 state 中的数据并保持响应式。

2.2 输出

该模块输出 useStore 和 createStore 两个方法,其中 createStore 方法可以将参数中的 state 变成响应式的,getters 响应式获取 state 中的数据并且支持多个方法,另外还支持 commit 和 dispath

2.3 补充

commit 方法会直接存在于 new Store 创建的实例中,这个不同于 dispatch 方法,它只存在于 Store 的实例对象中,这个是实例属性的新写法,可以参考 ES6入门

3. 源码

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 };
复制代码

4. 总结

通过学习手写 Vuex 的代码可以加深对官网文档的理解,同时注意平常使用的时候需要保持响应性,并且只通过 commit 方法进行显示修改数据。

猜你喜欢

转载自blog.csdn.net/sinat_17775997/article/details/126213348