你不知道action与mutation怎么被调用的?赶忙回去看啊Vuex源码学习(七)action和mutation如何被调用的(调用篇))vue
上两个小节已经讲述了commit与dispatch如何调用mutation与action的,可是action中有几个参数感受涉及到了一些咱们遗漏(故意不讲)的点。ajax
在installModule的时候 给每一个模块绑定了一个属性context。 经过makeLocalContext函数建立的,在注册action、mutation和getters都有使用。这个context是什么呢?vuex
咱们按照类型分析bash
// 查看全名,若是没有全名 多是根模块或者没有设置命名空间
const noNamespace = namespace === '';
// 若是没有全名 就使用全局(store)上的disptach
// 有全名的话 构建一个新的dispatch
// 这个新的dispatch仍然接收三个参数(与store上的dispatch同样)
//
dispatch: noNamespace ? store.dispatch : (_type, _payload, _options) => {
//unifyObjectStyle 对额外传入的_options没有任何处理 只是肯定一下位置
const args = unifyObjectStyle(_type, _payload, _options)
// options 值没有发生变化
const { payload, options } = args
let { type } = args
// 在disptach的时候是否指定选择root(根)
// 若是options设置为{root : true} 那么就会跳过下面
if (!options || !options.root) {
// 拼接真正的名字
type = namespace + type
if (process.env.NODE_ENV !== 'production' && !store._actions[type]) {
console.error(`[vuex] unknown local action type: ${args.type}, global type: ${type}`)
return
}
}
// 调用(补全名字后)的action
return store.dispatch(type, payload)
},
复制代码
这段代码咱们能够看出来,local对象(也就是模块的context属性)中的dispacth会在未指定使用根模块名字时,会把dispatch调用的名字强行加上这个模块的全名,用这个dispatch调用的action都会变成你这个模块下的action函数
通俗的讲 咱们想要调用A模块(有命名空间的某个action B)须要作的是post
this.$store.dispatch('A模块的全名/B的名字');
复制代码
在A模块的action中想要使用dispatch来作一些事情。学习
actions.js
export const ajaxGetUserName = ({dispatch})=>{
// 这个时候用dispatch调用本身模块内的其他的action不须要加上全名
dispatch('ajaxGetUserAge');
// 想要变成和根模块同样的dispatch 须要加上一个options注明{root : true}
// 这个时候dispatch就会变成全局的 不会主动帮你拼接全名了
}
export const ajaxGetUserAge = () => {
// do something
}
复制代码
同理local对象下的commit也是作了一样的事情,ui
两个方法说完了,下面该讲两个属性了this
这两个属性就是咱们的getters与state,可是这是咱们local对象中,也就是局部模块下的getters与state。getters与state如何建立的 getters 首先判断全名是否是为空,为空就返回store对象的getters,有的话就建立局部getters。与其说是建立不如说是代理lua
makeLocalGetters源码
function makeLocalGetters (store, namespace) {
// 设计思想
//其实咱们并不须要建立一套getters,
// 只要咱们在local中经过getters来获取一些局部模块的值的时候,
// 能够被代理到真正存放这些getters的地方。
// 建立代理对象
const gettersProxy = {}
// 找到切割点
const splitPos = namespace.length
Object.keys(store.getters).forEach(type => {
// skip if the target getter is not match this namespace
// 得去getters里面找一下有没有这个namespace为前缀的getter。
// 没有就找不到了
if (type.slice(0, splitPos) !== namespace) return
// extract local getter type
// 拿到模块内注册的那个局部的getter名字
// 全名是set/getName
// localType就是getName
const localType = type.slice(splitPos)
// Add a port to the getters proxy.
// Define as getter property because
// we do not want to evaluate the getters in this time.
// 完成代理任务,
// 在查询局部名字是被代理到对应的store.getters中的(全名)getter
Object.defineProperty(gettersProxy, localType, {
get: () => store.getters[type],
enumerable: true
})
})
//返回代理对象
return gettersProxy
}
复制代码
建立局部的getters就是一个代理的过程,在使用模块内使用(没有加上命名空间的)getters的名字,会被代理到,store实例上那个真正的(全名的)getters。
state 这个相对来讲就简单不少了
context是如何被建立的你们已经比较了解了。context的做用是什么? (local就是contenxt)以前说过注册mutation、action、getters都用到了local。用他们干什么?一一介绍
1. 注册mutation
2. 注册dispatch
可是只给了dispatch传入了store的getters与state(虽然有了这俩你想要什么放在vuex的数据都能获得),并无给store的dispatch与mutation。
这就说名dispatch能够查看store中的全部数据,你放在vuex里面的数据我均可以看,可是你想改不使用特殊手段,很差意思只能改本身模块的。
3. 注册getters
在注册中咱们能够看到,vuex对这个改变数据的权限控制的很严格,可是查看数据控制的很松,改只能改本身模块的,查你愿意怎么看都OK。
{root:true}
)来解开局部模块的限制。这个章节结束,咱们全部和模块有关的内容就已经完结了。 对于模块作一个小的总结。
因此模块为Vuex提供了不少方便,方便的去获取数据、修改数据。那么Vuex真正的数据仓库在哪里?数据都存储在哪里? 咱们下一章见