Vuex

133 阅读1分钟

Vue.use(Vuex)

// 混入 beforeCreate 钩子
// this.$store = 传入 vue 配置的store实例
// 子组件: this.$store = parent.$store

new Vuex.Store({})

const store = new Vuex.Store({
  modules: {
    modules1,
    modules2
  },
  getters,
  state: {},
})

state 数据 { name, age }
mutations = {
  // 同步
  SET_NAME: (state, payload) => {
    state.name = payload
  },
}
const actions = {}

class Store

constructor(options = {}) {
  // 注意几个重要属性
  this._actions = {}        // 所有的 action 包括子模块的
  this._mutations = {}      // 所有的 mutation 包括子模块的
  this._wrappedGetters = {} // 所有的 getter 包括子模块的

  // this 是 store 实例
  // this._modules 是 ModuleCollection 实例
  // this._modules.root 是 Module 实例
  this._modules = new ModuleCollection(options)
  // this._modules.root = Module // 根模块 module 实例
  // 看一下 Module 实例的属性
  {
    _children: {} // 子 module 实例
    state: 自身模块的state
    _rawModule
    namespace
  } 
}

installModule(this, state, [], this._modules.root)

{
  const namespace = store._modules.getNamespace(path) // 得到模块 namespace
  parentState[moduleName] = module.state // 子模块的 state 都放在 rootState 上 
  
  const local = module.context = makeLocalContext(store, namespace, path)

  // module.context
  {
    dispatch: noNamespace ? store.dispatch : (type, payload) => {
      // 到时候就从 this._actions 中找 
      return store.dispatch(namespace + type, payload)
    }
    commit: noNamespace ? store.commit : (type, payload, options) => {
      store.commit(namespace + type, payload, options)
    }
    getters: {
      get: noNamespace
        ? () => store.getters
        : () => makeLocalGetters(store, namespace)
    }
    // 子模块的state
    state: {
      get: () => getNestedState(store.state, path)
    }
  }

  将每个模块的 actions mutations getters 经过包装放在store实例上
  // mutations
  store._mutations[namespace + key] = [
    function wrappedMutationHandler (payload) {
      // handler 其实就是模块mutations中key对应的函数(用户指定)
      handler.call(store, local.state/* 模块自身的state */, payload)
    }
  ]

  // actions
  store._actions = {
    'namespace/actionName': function wrappedActionHandler (payload) {
      // handler 其实就是模块actions中key对应的函数(用户指定)
      let res = handler.call(store, {
        dispatch: local.dispatch,   // (type, payload) => store.dispatch(namespace + type, payload)
        commit: local.commit,       // 同上
        getters: local.getters,     // { key: store.getters[namespace + key] }
        state: local.state,       
        rootGetters: store.getters,
        rootState: store.state
      }, payload)
      // 异步处理
      if (!isPromise(res)) {
        res = Promise.resolve(res)
      }

      return res
    }
  }

  // getters
  store._wrappedGetters = {
    key: function wrappedGetter (store) {
      return rawGetter(      // 实际定义的getter函数(用户指定)
        local.state,         // local state
        local.getters,       // local getters
        store.state,         // root state
        store.getters        // root getters
      )
    }
  }
}

resetStoreState

store.getters = {}
const wrappedGetters = store._wrappedGetters
const computedObj = {}

computedObj[key] = partial(fn, store)
// 你可以把 getters 理解成 state 的计算属性,这里state属性收集了 getters 的watcher
computedCache[key] = computed(() => computedObj[key]())
Object.defineProperty(store.getters, key, {
  get: () => computedCache[key].value, // 缓存效果
  enumerable: true, 
})

// state 做响应式处理,组件调用属性的时候收集了组件的渲染watcher,通过 commit 执行改变state,触发重新渲染
store._state = reactive({
  data: state
})