import {
isObject } from "./util";
/**
* vuex 中使用的四个辅助函数的来源文件 /src/helpers.js。
* mapState,
* mapMutations,
* mapGetters,
* mapActions,
* createNamespacedHelpers
*/
/*
mapState 经过 调用normalizeNamespace() 之后,返回的结果,这个结果就是个函数。
我们调用的 mapState 是如下函数:
return (namespace, map) => {
//如果第一个参数 namespace 不是字符串。那就认为只有一个参数,该参数是个数组. 如:["user/updateName", "user/updateAge"]
if (typeof namespace !== "string") {
//将命名空间数组的数据统一到 map
map = namespace;
//设置namepace为空。
namespace = "";
//namespace 是 string,如果 namespace 不是以 “/” 结尾,则在尾部添加个 "/"
} else if (namespace.charAt(namespace.length - 1) !== "/") {
namespace += "/";
}
return fn(namespace, map);
};
第一个参数: namespace 是字符串,
第二个参数:states 是一个数组或者非null的对象。其元素或者value可以是函数。
==> 当然最终就是调用了 normalizeNamespace 的第一个参数指向的函数。
==> 由于函数内部有 this.$store 的方式,导致必须在 vue 环境下才能使用 mapState。
*/
export const mapState = normalizeNamespace((namespace, states) => {
//存储结果的对象,是个 {};
const res = {
};
//如果是在开发环境,且如果不是个可用的对象,则报红提示。
if (__DEV__ && !isValidMap(states)) {
console.error(
"[vuex] mapState: mapper parameter must be either an Array or an Object"
);
}
//将 states 归一化为数组。格式为: [{ key:key, value:value }, ...]
normalizeMap(states).forEach(({
key, val }) => {
/**
* 这里有一点需要注意:
* computed: {
* ...mapState(["user1/info", "user1/name"]);
* ...mapState("user2", ["info", "name"]);
* ...mapState({
* "info1": "user1/info",
* "info2": "user2/info"
* })
* ...mapState( "user", {
* "info1": "info1",
* "info2": "info2"
* })
* }
* 1、mapState 返回的结果是一个对象,对象的中属性key,对应的value都是函数。
* (1) 如果是数组,则 key 就是 1,2,3,4...
* (2) 在 vue 的 computed 创建时,会被数据劫持,key就是不含有 namespace 的key。
* (3) Object.keys( res ).forEach( key=>{
* Object.defineProperty( vue, key, {
* get(){
* res[key]();
* }
* })
* })
* 通过数据劫持之后,就做到了 this.info1 就能调用 mappedState() 方法。
*
* 2、关于 ...mapState("user", [info(state, getter){}, ...]) 的形式:
* info( state, getter ){ ... } 通过该函数的返回值作为结果。
*/
res[key] = function mappedState() {
//注意这个 this 是引入 mapState 页面的 vue 实例。
//state 存储所有的 options 中的 state 数据。
let state = this.$store.state;
//getters 存储所有的 options 中的 getter 数据。
let getters = this.$store.getters;
//如果 namespace 存在,则去对应的子 module 查找 state 和 getter。
//否则就直接在 store 上找 state 和 getter。
if (namespace) {
//通过 namespace 找到指定的 module。
const module = getModuleByNamespace(this.$store, "mapState", namespace);
//如果不存在,则返回null。
if (!module) {
return;
}
//module.context 就是 store.js 的 local 对象。
//module.context.state 能通过闭包的方式获取到该module 对应的 namespace,path。
state = module.context.state;
//module.context.state 能通过闭包的方式获取到该module 对应的 namespace,path。且会从 store.getters 中获取。
getters = module.context.getters;
}
//如果val 是 mapState( [( state, getters )=>{ }] ) 的 ( state, getters )=>{ }, 则调用该函数获取返回值。
return typeof val === "function"
? val.<
vuex3源码注释系列 /src/helper.js mapState,mapMutation,mapGetter,mapAction 源码解析
于 2022-03-17 11:22:22 首次发布