vuex 项目回顾和使用 - 基础篇和原理篇

75 阅读1分钟

项目使用 vuex 做数据共享和管理。忙于业务开发时,只关注如何使用,却没想过为何使用。 现在有时间做总结了,在此记录一下。

总结共分三篇:基础篇和原理篇、实践篇、思考篇。建议先浏览一下思考篇的几个问题,再回看基础篇。

本文关注问题速览:

  • vuex几个基本概念及关系
    • store state module
    • getter
    • commit mutation action
    • 为什么有 actions 和 mutations
  • vuex 响应式原理

vuex几个基本概念及关系

store state module

state - state 为状态,Vuex 中的 state,可以理解为一个绑定到界面或组件的状态变量。

store - 每一个 Vuex 应用的核心就是 store(仓库)。“store”基本上就是一个容器,它包含着你的应用中大部分的 状态 (state)。

module - 当 store 过于臃肿时,可以拆分成子模块维护。实践篇有提及稍复杂的拆分方案。

getter

getter - 可以认为是 store 的计算属性(返回值会根据它的依赖进行缓存,当依赖值变化时,才重新计算)

在通过属性访问时是作为 Vue 的响应式系统的一部分缓存其中的

computed: {
  doneTodosCount () {
    return this.$store.getters.doneTodosCount // 属性访问
  }
}

commit mutation action

mutation - 改变 state 所有方法( dispatch | commit )中,最终要走的一步

commit - 触发 mutation 的入口,挂载在 store 对象上

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  }
})

store.commit('increment')

为什么有 actions 和 mutations

区分 actions 和 mutations 并不是为了解决竞态问题,而是为了能用 devtools 追踪状态变化

改变 state 状态,只要最后触发 mutation 就行

附上尤大的解释 www.zhihu.com/question/48…

vuex 响应式原理

参考文档地址 zhuanlan.zhihu.com/p/78981485

其实很简单:创造一个 vue 实例,借助 vue 的 data 响应式能力和 computed 数据监听能力。

  • store 上挂载一个vue实例,叫 store._vm。
  • state 注入到 _vm.data 中。
  • getters 借助 _vm.computed 做数据监听 + defineProperty 访问代理。

附上源码

function resetStoreVM (store, state, hot) {
  const oldVm = store._vm

  // 设置 getters 属性
  store.getters = {}
  const wrappedGetters = store._wrappedGetters
  const computed = {}
  // 遍历 wrappedGetters 属性
  forEachValue(wrappedGetters, (fn, key) => {
    // 给 computed 对象添加属性
    computed[key] = partial(fn, store)
    // 重写 get 方法
    // store.getters.xx 其实是访问了store._vm[xx],其中添加 computed 属性
    Object.defineProperty(store.getters, key, {
      get: () => store._vm[key],
      enumerable: true // for local getters
    })
  })

  const silent = Vue.config.silent
  Vue.config.silent = true
  // 创建Vue实例来保存state,同时让state变成响应式
  // store._vm._data.$$state = store.state
  store._vm = new Vue({
    data: {
      $$state: state
    },
    computed
  })
  Vue.config.silent = silent

  // 只能通过commit方式更改状态
  if (store.strict) {
    enableStrictMode(store)
  }
}