Vuex源码阅读(二) store内的getters实现逻辑

1. 准备工作

1) 创建一个store,state只包含一个count成员:

new Vuex.Store({
state: {
count: 0
},
mutations: {
increment(state) {
state.count++;
}
},
actions: {
incrementOfActive: ({ commit }) => {
commit('increment');
}
},
getters: {
countOfGetter: (state) => {
return state.count;
}
}
});

  

2) 创建一个Vue对象,并设置store

window.DEMO_VM = new Vue({
el: '#app',
store
});

2. Vuex对getter做了哪些处理

通过阅读Vuex的源码,发现对getter做了下面处理

2.1 进行局部化

说明:当创建Vuex.Store时,如果内部嵌套了多个stroe(Module),将进行局部化,目的是为了Module各自的getters都保持对各自state的访问。

代码

function registerGetter(store, type, rawGetter, local) {
if (store._wrappedGetters[type]) {
if (__DEV__) {
console.error(`[vuex] duplicate getter key: ${type}`);
}
return;
}
store._wrappedGetters[type] = function wrappedGetter(store) {
return rawGetter(
local.state, // local state
local.getters, // local getters
store.state, // root state
store.getters // root getters
);
};
}

2.2 注册为计算属性

说明:初始化内部变量_vm,将getter注册为_vm的计算属性。

// 获取getters内的每个getter封装到_vm
const wrappedGetters = store._wrappedGetters;
const computed = {};
forEachValue(wrappedGetters, (fn, key) => {
    computed[key] = partial(fn, store);
Object.defineProperty(store.getters, key, {
get: () => {
return store._vm[key];
},
enumerable: true // for local getters
});
});

store._vm = new Vue({
data: {
$$state: state
},
computed
});

3. 解析逻辑

3.1 $store.getters.countOfGetter值从哪里来

说明:虽然我们创建的countOfGetter的内部为"return state.count;",难道我们每次调用countOfGetter都是执行了对应的函数吗?

从2.2节的源码上看,Vuex对countOfGetter设置了get特性,每次调用都是从_vm.countOfGetter获取。

所以当调用 window.DEMO_VM.$store.getters.countOfGetter 时 → 实际上从返回为 window.DEMO_VM.$store._vm.countOfGetter。

这里要注意一点store.getters都被注册为了_vm的计算属性。

官方对计算属性好处介绍:“计算属性是基于它们的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值。”

总结:这样子也进一步说明store.getters保留了缓存特性。

3.2 修改了state,getters为什么会变更

说明:跟上面的说的getters注册为计算属性一样,_vm绑定了state与getters对应的关系,当变更state时,对应的getter也会发生改变。

4. 问题

4.1 为何不直接在组件外修改state?

既然可以通过"window.DEMO_VM.$store.state.count = 4" 这样操作来修改state,为什么还需要mutations、actions?

有下面几个原因:

1) 统一规范。如果都像这样在外部直接修改state,那么整个Vuex体系就会乱掉,直接当成了全局变量(缓存)来使用了。

2) hooks:mutations、actions内部的调用了都附加了Subscribe的处理。

(0)

相关推荐

  • 【Vue】状态管理

    页面应用需要Vuex管理全局/模块的状态,大型单页面组件如果靠事件(events)/属性(props)通讯传值会把各个组件耦合在一起.因 此需要Vuex统一管理,当然如是小型单页面应用,引用Vuex反 ...

  • Vue 给mapState中定义的属性赋值报错的解决方案

    Vue 给mapState中定义的属性赋值报错的解决方案

  • Vue2 源码阅读(三) 双向绑定原理

    Vue2 源码阅读(三) 双向绑定原理

  • vuex的模块化使用

    store文件如下 1.modules下文件是模块化的划分,里面的js有state,action,mutations.然后通过 export default { namespaced: true, s ...

  • vue中 Vuex

    一.什么是Vuex Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化. 状态,其实指的是实例之 ...

  • vue系列教程之微商城项目|vuex全局状态管理-加入购物车

    问题描述 vuex简介 vuex是vue项目中用于管理全局状态的插件,如果对状态二字不明了,就简单理解成全局变量即可. 全局状态管理方式有很多,千奇百怪,比如bus总线.自定义一个js文件等,感兴趣可 ...

  • uni-app开发经验分享三: Vuex实现登录和用户信息留存

    在做用户登录的过程中,其实最重要的是登录成功后的数据要怎么储存,储存到哪里,这里我分享一个利用vuex来实现用户登录和用户数据留存的方法 vuex代码如下: //引入vue和vuex import V ...

  • nuxt中使用Vuex

    问题 如何在nuxt中使用Vuex? 以官网例子, 模块方式引用--计数器为例子 图1 计数器示例 目录结构 图2 目录结构 js模块写法 // user.js // state为一个函数, 注意箭头 ...

  • 一切前端概念,都是纸老虎

    (给前端大学加星标,提升前端技能.) 作者:姜小抖 https://zhuanlan.zhihu.com/p/53599723 这篇文章试着聊明白这一堆看起来挺复杂的东西.在聊之前,大家要始终记得一句 ...

  • Vue2 源码阅读(二) new Vue()做了什么

    Vue2 源码阅读(二) new Vue()做了什么

  • 一个超级实用的源码阅读小技巧

    在学习编程的路途漫漫,优秀的源码是非常珍贵的学习资源,阅读源码也是有效提高自己的一个好方法. 工欲善其事必先利其器: 我发现函数调用图可以让我们更加直观地了解到源码函数直接的调用和层次关系,提高阅读源 ...

  • spark源码阅读--shuffle过程分析 ShuffleManager(一)

    ShuffleManager(一) 本篇,我们来看一下spark内核中另一个重要的模块,Shuffle管理器ShuffleManager.shuffle可以说是分布式计算中最重要的一个概念了,数据的j ...

  • dubbo源码阅读之服务目录

    服务目录 服务目录对应的接口是Directory,这个接口里主要的方法是 List<Invoker<T>> list(Invocation invocation) throws ...

  • 手把手教学APK反编译实现源码阅读

    手把手教学APK反编译实现源码阅读

  • Vue2.x 响应式部分源码阅读记录

    之前也用了一段时间Vue,对其用法也较为熟练了,但是对各种用法和各种api使用都是只知其然而不知其所以然.最近利用空闲时间尝试的去看看Vue的源码,以便更了解其具体原理实现,跟着学习学习. Proxy ...

  • Mybatis源码阅读套路,一次性打包发您~

    很多人看源码都不知道如何看,今天来教教大家如何看源码. 前提是我们需要对整个Mybatis的原理.工作流程和模块进行一个整体的直知晓,另外还要有使用经验. 建议先看这两篇文章: 本文主要内容: 源码下 ...

  • redis 5.0.7 源码阅读——动态字符串sds

    redis中动态字符串sds相关的文件为:sds.h与sds.c 一.数据结构 redis中定义了自己的数据类型"sds",用于描述 char*,与一些数据结构 1 typedef ...