vuex 源码解析(三) getter属性详解
有时候我们需要从store中的state中派生出一些状态,例如:
<div id="app">
<p>{{reverseMessage}}</p>
</div>
<script>
const store = new Vuex.Store({
state:{reverseMessage:'Hello Vue!'}
})
new Vue({
el:'#app',
store,
computed:{
reverseMessage:function(){return this.$store.state.reverseMessage.split('').reverse().join('')}
}
})
</script>
如果多个组件需要用到此属性,我们要么复制这个函数,或者抽取到一个共享函数然后在多处导入它---无论哪种方式都不是很理想
writer by:大沙漠 QQ:22969969
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>
这样在vuex内部就把reverseMessage这个属性给实现了,还是很好用的,vuex官网里说我们可以把getter当作计算属性一样来使用,事实上vuex内部也是把getter定义为vue的computed计算属性来实现的。
源码分析
在创建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
}); /*略*/
}
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了
例子执行到这里对应的_wrappedGetters如下:
最后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的响应式设计了。
vuex 源码解析(三) getter属性详解的更多相关文章
- jQuery 源码解析(三) pushStack方法 详解
该函数用于创建一个新的jQuery对象,然后将一个DOM元素集合加入到jQuery栈中,最后返回该jQuery对象,有三个参数,如下: elems Array类型 将要压入 jQuery 栈的数组元素 ...
- guava-retrying 源码解析(停止策略详解)
一.停止策略相关类 1.停止策略接口:StopStrategy接口,只有一个抽象方法 // 是否应该停止重试.不同的停止策略有不同的实现.boolean shouldStop(Attempt fail ...
- guava-retrying 源码解析(等待策略详解)
一.等待策略相关类: 1.等待策略接口:WaitStrategy接口 该接口只有一个方法,就是返回尝试失败之后,下一次尝试之前的等待时间.long computeSleepTime(Attempt f ...
- guava-retrying 源码解析(阻塞策略详解)
这是一种策略,用于决定重试者应如何在重试尝试之间进行阻止.通常这只是一个thread.sleep(),但是如果需要的话,实现可能更复杂. 一.阻塞策略相关的类或接口 1.阻塞策略接口:BlockStr ...
- Celery 源码解析三: Task 对象的实现
Task 的实现在 Celery 中你会发现有两处,一处位于 celery/app/task.py,这是第一个:第二个位于 celery/task/base.py 中,这是第二个.他们之间是有关系的, ...
- Mybatis源码解析(三) —— Mapper代理类的生成
Mybatis源码解析(三) -- Mapper代理类的生成 在本系列第一篇文章已经讲述过在Mybatis-Spring项目中,是通过 MapperFactoryBean 的 getObject( ...
- ReactiveCocoa源码解析(三) Signal代码的基本实现
上篇博客我们详细的聊了ReactiveSwift源码中的Bag容器,详情请参见<ReactiveSwift源码解析之Bag容器>.本篇博客我们就来聊一下信号量,也就是Signal的的几种状 ...
- ReactiveSwift源码解析(三) Signal代码的基本实现
上篇博客我们详细的聊了ReactiveSwift源码中的Bag容器,详情请参见<ReactiveSwift源码解析之Bag容器>.本篇博客我们就来聊一下信号量,也就是Signal的的几种状 ...
- React的React.createRef()/forwardRef()源码解析(三)
1.refs三种使用用法 1.字符串 1.1 dom节点上使用 获取真实的dom节点 //使用步骤: 1. <input ref="stringRef" /> 2. t ...
随机推荐
- MySQL数据库查询所有表名
查找指定库中所有表名 select table_name from information_schema.tables where table_schema='db_name'; 注:替换db_nam ...
- this泛指函数的上下文
this泛指函数的上下文 当前函数运行的类型上下文.
- Python Turtle绘画初学编程——六芒星,浪形圈
老师上课说可以自学一下python中的绘图turtle,就自己初步学习了一下,做了两个简单的绘图——六芒星和浪形圈(其实我也不知道该叫它什么,就照样子编了个词
- python基础(14):生成器、列表推导式
1. 生成器 什么是⽣成器?⽣成器实质就是迭代器. 在python中有三种⽅式来获取⽣成器: 1. 通过⽣成器函数 2. 通过各种推导式来实现⽣成器 3. 通过数据的转换也可以获取⽣成器 ⾸先,我们先 ...
- numpy 和 tensorflow 中的各种乘法(点乘和矩阵乘)
点乘和矩阵乘的区别: 1)点乘(即" * ") ---- 各个矩阵对应元素做乘法 若 w 为 m*1 的矩阵,x 为 m*n 的矩阵,那么通过点乘结果就会得到一个 m*n 的矩阵. ...
- Javase之集合泛型
集合泛型知识 泛型 是一种把类型明确工作推迟到创建对象或者调用方法的时候才明确的特殊类型. 也称参数化类型,把类型当成参数传递. 在jdk1.5中出现.一般来说经常在集合中使用. 格式 <数据类 ...
- Qt Creator单步调试快捷键F10经常失灵问题
使用Qt Creator调试程序的时候经常会遇到F10单步调试快捷键不响应的问题. 打开调试菜单如下:有两个快捷键为F10的调试菜单项,于是快捷键冲突了! 解决办法:废话不说,直接上图 由于Start ...
- 【转载】Gradle for Android 第六篇( 测试)
由于现阶段Android开发趋于敏捷开发,再加上国内大大小小的互联网公司都在做app,导致很多这会是一个系列,所以如果你看完这篇文章,请看下列文章: 开发人员对单元测试没有基本的概念,但是本篇博文不会 ...
- Xamarin学习(一)---- 环境准备
前言: 摸索学习Xamarin的应用,以此博客跟进学习进度. 介绍: Xamarin 提供了用于移动设备.平板电脑和桌面应用程序的跨平台开发解决方案.Xamarin 产品依赖于 Apple 和 ...
- 【Servlet】JavaWeb应用的执行流程
Tomcat与Servlet简介 Tomcat Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由Apache.S ...