• 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的处理。

  • 相关阅读:
    js 数据结构-栈与队列
    mysql (已解决)Access denied for user 'root'@'localhost' (using password: NO)
    mysql (已解决p)MYSQL5.7启动不了,本地计算机上的 MySQL57 服务启动后停止。
    mysql 慢查询日志,灾难日志恢复,错误日志
    php json的相关操作
    (转)LitJson 遍历key
    (转)用Eclipse进行C++开发时Bianry not found的问题解决
    (转) 在Eclipse中进行C/C++开发的配置方法(20140721最新版)
    (转)如何在eclipse的配置文件里指定jdk路径
    (转)mongodb分片
  • 原文地址:https://www.cnblogs.com/polk6/p/13079949.html
Copyright © 2020-2023  润新知