Vuex 简单模拟

「这是我参与2022首次更文挑战的第27天,活动详情查看:2022首次更文挑战

模拟 Vuex

上回,本章要进行 手写Vuexinstallstore部分方法

install 方法

install是一个对于一个Vue插件,都需要具备的一个方法。在我们实现Vuex的过程中,我们需要在此方法中,需要将Vue实例保存起来,方便我们之后的调用。然后我们需要将store赋值给Vue.prototype.$store

如何保存Vue实例?

vue的官方文档中也很明确的说到:

Vue.js 的插件应该暴露一个 install 方法。这个方法的第一个参数是 Vue 构造器,第二个参数是一个可选的选项对象

那么我们只需要如此操作即可:

let _Vue = null

function install (Vue) {
  _Vue = Vue
}
复制代码

store赋值给Vue.prototype.$store

在将store赋值给Vue.prototype.$store后,项目中的所有组件都可以通过this.$store来获取Vuex下面的仓库,从而可以在所有组件中共享状态。

我们可以通过混入beforeCreate来获取Vue实例,获取选项中的Vue对象

function install (Vue) {
  _Vue = Vue
  _Vue.mixin({
    beforeCreate () {
      // 如果已经注册了,就不需要再次进行注册了
      if (this.$options.store) {
        _Vue.prototype.$store = this.$options.store
      }
    }
  })
}
复制代码

到这里 install 方法就结束了

Store 类

需要包含的内容

  • state - 响应式的
  • getters
  • mutations
  • actions
  • commit 提交 mutations
  • dispatch 分发 actions

1.首先需要一个构造函数

  1. 获得参数

    构造函数中,需要初始化时的参数

    constructor (options) {
        const {
          state = {},
          getters = {},
          mutations = {},
          actions = {}
        } = options
    }
    复制代码
  2. state转换为响应式

    然后我们需要将state转换为响应式的对象,我们需要调用observable对数据进行响应式处理:

    this.state = _Vue.observable(state)
    复制代码
  3. getters处理

    getters是一个对象,对象中有一些方法,这些方法都需要接受state参数,并且最终都有一个返回值。一般情况下就是对state做一些处理后返回,而只有当我们访问了getters方法时,才会有有值返回,所以我们可以用Object.defineProperty转换get

    this.getters = Object.create(null)
    
    Object.keys(getters).forEach(key => {
      Object.defineProperty(this.getters, key, {
        get: () => getters[key](state)
      })
    })
    复制代码
  4. mutations、actions 只需要存储到对应的方法中在commitdispatch中获取就好

如此命名主要是不希望外部可以随便访问

this._mutations = mutations
this._actions = actions
复制代码
  1. commitdispatch
commit (type, payload) {
    this._mutations[type](this.state, payload)
}

dispatch (type, payload) {
    this._actions[type](this, payload)
}
复制代码

五、总结

最后我们回过来看文章开始提出的5个问题。

1.  使用Vuex只需执行 Vue.use(Vuex),并在Vue的配置中传入一个store对象的示例,store是如何实现注入的?


Vue.use(Vuex) 方法执行的是install方法,它实现了Vue实例对象的init方法封装和注入,使传入的store对象被设置到Vue上下文环境的 s t o r e 中。因此在 V u e C o m p o n e n t 任意地方都能够通过 t h i s . store中。因此在Vue Component任意地方都能够通过`this. store`访问到该store。

2.  在执行dispatch触发action(commit同理)的时候,只需传入(type, payload),action执行函数中第一个参数store从哪里获取的?


:store初始化时,所有配置的action和mutation以及getters均被封装过。在执行如dispatch('submitOrder', payload)的时候,actions中type为submitOrder的所有处理方法都是被封装后的,其第一个参数为当前的store对象,所以能够获取到 { dispatch, commit, state, rootState } 等数据。

源码中还有一些工具函数,如有兴趣可以打开源码看看,这里不再细述。

我们本章进行模拟的主要目的还是,想要了解Vuex的工作基本流程

猜你喜欢

转载自juejin.im/post/7068469851634794532