Bootstrap

【Vuex 源码学习】第四篇 - Vuex 中 Getters 的实现

一,前言

上篇,主要介绍了 Vuex 中 State 状态的实现,主要涉及以下几个点:

  • 创建 Store 类中的 State 状态;

  • 借助 Vue 实现 State 状态的响应式;

本篇,继续介绍 Vuex 中 getters 的实现;

二,前文回顾

在上一篇中,实现了 Vuex 中的 State 状态:

  • 创建了 Store 类,实例化时传入 options 选项;

  • 借助 Vue 实现 State 对象的响应式数据;

  • 通过属性访问器,提供外部访问 ;

本篇继续处理 options 选项中的 getters 属性;

  • getters 属性是具有缓存效果的,相当于 Vue 中的 computed 属性;

  • 多次取值时,若值不变化就不会更新视图,即不会调用方法;

三,保存 options 选项中的 getters 属性

Object.defineProperty 将 中用户定义的方法,保存到 Store 实例中:

// src/vuex/store.js

import applyMixin from "./mixin";

export let Vue;

export class Store {
  constructor(options) { // options:{state, mutation, actions}
    // 处理 getters...
    // options.getters;// 外部传入选项中的 getters:内部包含多个方法
    this.getters = {};// 声明 store 实例中的 getters 对象
    // 页面通过“{{this.$store.getters.getPrice}}”取值,取的是 getters 对象中的属性
    // 所以,需要将将用户传入的 options.getters 属性中的方法,转变成为 store 实例中的 getters 对象上对应的属性
    Object.keys(options.getters).forEach(key=>{
      Object.defineProperty(this.getters, key, {
        // 取值操作时,执行 options 中对应的 getters 方法
        get: () => options.getters[key](this.state)
      })
    });
  }
}

此时,当页面通过访问 store 实例中 getters 对象中的getPrice 属性时,实际访问的是 中的 getPrice 方法;

四,Vuex 中 getters 缓存效果实现

我们说,vuex 中的 getters 属性是具有缓存效果的;

修改 App.vue,尝试多次调用 store 实例 getters 对象中的属性:

打印 getters 方法执行 log:

// src/store/index.js

import Vue from 'vue';
import Vuex from '@/vuex';

Vue.use(Vuex);

const store = new Vuex.Store({
  state: {
    num: 10
  },
  getters: {
    getPrice(state) {
      console.log("进入 getters - getPrice")
      return state.num * 10
    }
  }
});

export default store;

执行结果:

页面中三次访问 store 实例中 getters 属性中的 getPrice 方法,控制台会打印三次 log,这说明了每次访问都会真正调用一次 getters 中定义的方法,目前 Vuex 的 getters 是不具备缓存效果的;

如何实现 Vuex 中 getters 缓存功能?

可以利用 Vue 中原生的 computed 计算属性:

// src/vuex/store.js

import applyMixin from "./mixin";

export let Vue;

export class Store {
  constructor(options) { // options:{state, mutation, actions}
    // 获取 options 选项中的 state 对象
    const state = options.state;  
    // 获取 options 选项中的 getters 对象:内部包含多个方法
    const getters = options.getters;
    // 声明 store 实例中的 getters 对象
    this.getters = {};
    // 将 options.getters 中的方法定义到计算属性中
    const computed = {}

    // 页面通过“{{this.$store.getters.getPrice}}”取值,取的是 getters 对象中的属性
    // 所以,需要将将用户传入的 options.getters 属性中的方法,转变成为 store 实例中的 getters 对象上对应的属性
    Object.keys(getters).forEach(key => {
      // 将 options.getters 中定义的方法,放入计算属性 computed 中,即定义在 Vue 的实例 _vm 上
      computed[key] = () => {
        return getters[key](this.state)
      }

      // 将 options.getters 中定义的方法,放入store 实例中的 getters 对象中
      Object.defineProperty(this.getters, key, {
        // 取值操作时,执行计算属性逻辑
        get: () => this._vm[key]
      })
    });

    this._vm = new Vue({
      data: {
        $$state: state
      },
      computed // 将 options.getters 定义到 computed 实现数据缓存
    })
  }
}

运行查看效果:

多次访问 store 实例中 getters 属性中的 getPrice 方法,控制台仅输出 1 次 log,说明已成功实现 Vuex 的 getters缓存效果;

五,结尾

本篇,介绍了 Vuex 中 getters 的实现,主要涉及以下几个点:

  • 将选项中的 getters 方法,保存到 store 实例中的 getters 对象中;

  • 借助 Vue 原生 computed,实现 Vuex 中 getters 的数据缓存功能;

下一篇,Vuex 中 Mutation 的实现;