2-vuex4.0核心源码

95 阅读1分钟

思路

  • app.use的语法怎么去注册的插件的?
    • app.use(store); 会执行的是store.install方法,所以得在这里面关联上Vue
    • app.config.globalProperties.store;让每一个组件实例都有一个store;让每一个组件实例都有一个store
  • 怎么才能让全局的组件能用共享store?
    • provide/inject使用注入的方式
  • 数据怎么去响应式: vue的reactive钩子,reactive -> proxy的方式实现代理的
  • 怎么去实现这些函数调用之间联动了?
    • 发布订阅模式

下面就是我实现的代码,大佬看到了可以斧正

import { inject, reactive } from 'vue';
const storeKey = "store";

// 获取对象的属性和值
function foreachObjectProp(obj, cb) {
  Object.keys(obj).forEach(item => {
    cb(item, obj[item]);
  })
}

export class Store {
  // 配置项
  constructor(options) {
    // 响应式的数据
    this.vm = reactive(options);
    let getters = options.getters;
    // getters
    this.getters = {};
    foreachObjectProp(getters, (key, value) => {
      Object.defineProperty(this.getters, item, {
        get: () => {
          return value(this.state);
        }
      })
    });
    // actions mutations
    let mutations = options.mutations;
    this.mutations = {};
    foreachObjectProp(mutations, (key, value) => {//发布订阅
      this.mutations[key] = (data) => {
        value(this.state, data);
      };
    })
    let actions = options.actions;
    this.actions = {};
    foreachObjectProp(actions, (key, value) => {//发布订阅
      this.actions[key] = (data) => {
        value(this, data);// 这里用this 才能 { commit }
      };
    })

  }
  install(app, key) {//相对于vue2中的vue实例
    console.log(app);
    // 让每一个组件实例都有一个$store
    app.config.globalProperties.$store = this;
    // 给每个组件添加一个store实例
    app.provide(key || storeKey, this);
  }
  // 获取响应式的数据
  get state() {
    return this.vm;
  }
  commit = (key, payload) => {
    this.mutations[key](payload);
  }
  dispatch = (key, payload) => {
    this.actions[key](payload);
  }
}

// 创建一个store
export function createStore(options) {
  return new Store(options);
} 

// 在使用的组件中得到一个store
export function useStore(key = null) {
  // 这样组件中就能获取到值
  return inject(key || storeKey);
}