1、Vuex允许我们在store中定义"getter"(可以认为是store的计算属性),就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算
每个getter对应的匿名函数可以带四个参数,分别是当前模块的state、getter和根模块的state、getter,例如:
<div id="app">
<p>{{reverseMessage}}</p>
</div>
<script>
const store = new Vuex.Store({
state:{reverseMessage:'Hello Vue!'},
getters:{
reverseMessage:function(state){return state.reverseMessage.split('').reverse().join('');}
}
})
new Vue({
el:'#app',
store,
computed:{
reverseMessage:function(){return this.$store.getters.reverseMessage}
}
})
</script>
2、看源码
2.1 在创建Vuex.Store()初始化时会执行installModule()安装根模块,和getter相关的如下:
function
installModule (store, rootState, path, module, hot) { //安装模块
/*略*/
module.forEachGetter(function (getter, key) { //遍历module模块的getters对象,如果找到了,则执行这个匿名函数 参数1:每个getter值 key:对应的键名
var namespacedType = namespace + key; //拼凑命名空间+键名,例如:a/computedCount
registerGetter(store, namespacedType, getter, local); //依次执行registerGetter
});
/*略*/
}
2.2 registerGetter用于注册每个getter,如下:
function registerGetter (store, type, rawGetter, local) { //注册getter
if (store._wrappedGetters[type]) { //如果store._wrappedGetters下已经有key了
{
console.error(("[vuex] duplicate getter key: " + type)); //则报错,即不允许重复
}
return
}
store._wrappedGetters[type] = function wrappedGetter (store) { //保存到store._wrappedGetters对应的type里
return rawGetter( //执行store函数 四个参数分别为local state、local getters、root state、root getters
local.state, // local state
local.getters, // local getters
store.state, // root state
store.getters // root getters
)
};
}
这样在 store._wrappedGetters中就存储了对应的getter了,是一个匿名函数,函数有一个参数是store,这个是vuex.store()的实例,一会创建vue实例时会传入的,这样在geter里就能访问到根模块的state和getters了
2.3 最后Vuex走到resetStoreVM()去创建一个Vue实例时,和getter有关的逻辑如下:
function resetStoreVM (store, state, hot) { //重新存储数据
var oldVm = store._vm;
// bind store public getters
store.getters = {};
var wrappedGetters = store._wrappedGetters; //获取store的所有getter信息,也就是上面保存的数据,每个值是一个匿名函数
var computed = {}; //用于存储最后的计算属性
forEachValue(wrappedGetters, function (fn, key) { //遍历wrappedGetters
// use computed to leverage its lazy-caching mechanism
computed[key] = function () { return fn(store); }; //将computed[key]定义为一个函数表达式,内部返回fn()执行后的结果,传入store参数,这样在geter里就能访问到根模块的state和getters了
Object.defineProperty(store.getters, key, { //设置store.getters的key的访问器属性,这样就可以通过store.getters.aaa访问到某个具体的值了
get: function () { return store._vm[key]; },
enumerable: true // for local getters
});
});
/*略*/
}
之后如果有修改了state里的信息,getter里的信息都会自动更新的,这个归功于Vue的响应式设计了。