vuex数据调用,使用辅助函数mapState、mapMutations、mapActions、mapGetters的详解

在我们使用vuex调取公共数据时,当一个组件需要获取多个状态或调用多个方法的情况下,将这些状态都声明为计算属性、多次书写引用方法,会有些重复和冗余。为了解决这个问题,我们使用辅助函数mapState、mapMutations、mapActions、mapGetters,主要目的是为了简洁自己的代码,对引用数据进行统一管理。

以项目的store中module为doctorInfo的模块来举例:


export  default {

    namespaced: true,

    state: {
        data: {},
    },

    mutations: {

        setDoctorInfo(state, value) {
            state.data = { ...state.data, ...value };
        },

    },

    actions: {

         asyncGetInfo({ commit, state }, value) {   }

    },

    getters: {

         getDataParams: state => key => {
                return state.data[key];
         },

    }

};

目前项目中使用时,是根据以下方法调取数据:


export  default{

    computed: {

        dataInfo() {
                return  this.$store.state.doctorInfo.data
        },

        newParam() {
                return  this.$store.getters['doctorInfo/getDataParams']
        }

    },

    methods: {

        setDoctorInfo() {
                return  this.$store.commit('doctorInfo/setDoctorInfo',  info)
        },    

        getInfo(params) {
                return   this.$store.dispatch('doctorInfo/asyncGetInfo', params);
        }

    }

}

辅助函数的映射关系:

mapState > computed

mapGetters > computed

mapMutations > methods

mapActions > methods

使用了辅助函数mapState、mapMutations、mapActions、mapGetters代码会显得简单很多:

import {mapState、mapMutations、mapActions、mapGetters} from 'vuex'
export  default {
    computed: {
        ...mapState('doctorInfo', {
            dataInfo: state => state.data    // 自定义命名dataInfo
        }),
       // 或者
       //  ...mapState({
      //      dataInfo: state => state.doctorInfo.data   // 自定义命名dataInfo
      //   }),
        ...mapGetters('doctorInfo', ['getDataParams'],
    },
    methods: {
        ...mapMutations('doctorInfo', ['setDoctorInfo']),
        ...mapActions('doctorInfo', ['asyncGetInfo']),
    }
}

上面可以看出mapState把doctorInfo模块state中的data映射成当前this下的dataInfo,但是mapActions, mapMutations, mapGetters这些怎么办,直接一个[]是很方便,但是如果引入方法和vue实例中的方法命名重复了,或者想对引入方法进行自定义命名,这种情况下该怎么办呢?

官网中只是这么讲的:

  ...mapActions([
    'some/nested/module/foo', // -> this['some/nested/module/foo']()
    'some/nested/module/bar' // -> this['some/nested/module/bar']()
  ])

或者:

 ...mapActions('some/nested/module', [
    'foo', // -> this.foo()
    'bar' // -> this.bar()
  ])

一般情况下,这种是够用的,但对于解决我们上面说的命名重复问题,很明显没有什么帮助。。那就只能去看看vuex中的源码,去看看对于mapActions这些方法是如何进行传参的:

var mapActions = normalizeNamespace(function (namespace, actions) {
    var res = {};
    if ( !isValidMap(actions)) {
      console.error('[vuex] mapActions: mapper parameter must be either an Array or an Object');
    }
    normalizeMap(actions).forEach(function (ref) {
      var key = ref.key;
      var val = ref.val;

      res[key] = function mappedAction () {
        var args = [], len = arguments.length;
        while ( len-- ) args[ len ] = arguments[ len ];

        // get dispatch function from store
        var dispatch = this.$store.dispatch;
        if (namespace) {
          var module = getModuleByNamespace(this.$store, 'mapActions', namespace);
          if (!module) {
            return
          }
          dispatch = module.context.dispatch;
        }
        return typeof val === 'function'
          ? val.apply(this, [dispatch].concat(args))
          : dispatch.apply(this.$store, [val].concat(args))
      };
    });
    return res
  });

源码中mapActions(mapState、mapMutations、mapGetters也一样)一开始都会调用一个normalizeMap 的方法,我们来看下这个normalizeMap方法:

 /**
   * Normalize the map
   * normalizeMap([1, 2, 3]) => [ { key: 1, val: 1 }, { key: 2, val: 2 }, { key: 3, val: 3 } ]
   * normalizeMap({a: 1, b: 2, c: 3}) => [ { key: 'a', val: 1 }, { key: 'b', val: 2 }, { key: 'c', val: 3 } ]
   * @param {Array|Object} map
   * @return {Object}
   */
  function normalizeMap (map) {
    if (!isValidMap(map)) {
      return []
    }
    return Array.isArray(map)
      ? map.map(function (key) { return ({ key: key, val: key }); })
      : Object.keys(map).map(function (key) { return ({ key: key, val: map[key] }); })
  }
  可以看出,是它在处理mapActions中传入的第二个参数 ['asyncGetInfo'],normalizeMap会把入参转化成[{key: 'asyncGetInfo', val: 'asyncGetInfo'}]数组,我们可以看到如果传入的不是数组的话,normalizeMap会把入参当做对象来处理,依然把对象转化为{key: xxx,  val: xxx,}的形式,最后再以数组返回。
  所以要解决上面函数名重复的问题,我们可以在mapActions的第二个参数传入一个对象就行了,问题基本就快解决了,但这个对象的key是'asyncGetInfo'还是自定义命名(例如getInfo)呢?

这是我们就得回到mapActions的源代码了,看看最终执行的是key还是val了:

return typeof val === 'function'
          ? val.apply(this, [dispatch].concat(args))
          : dispatch.apply(this.$store, [val].concat(args))

可以看出,真正执行actions的是根据val,所以我们的问题有答案了,直接自定义命名方法:(第二种写法)

methods: {
        ...mapActions('doctorInfo', {
            getInfo: 'asyncGetInfo'
        }),
}

根据源码的 typeof val === 'function', 以下一段可以看出, 还是有另外一种用法的:

return typeof val === 'function'
          ? val.apply(this, [dispatch].concat(args))
          : dispatch.apply(this.$store, [val].concat(args))

第三种用法:

methods: {
        ...mapActions('doctorInfo', {
            getInfo(dispatch, params){
                dispatch('asyncGetInfo', params);
            }
        }),
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容

  • 听说成年人的自尊都是工资给的,我已经没有自尊两个多月了,哈哈哈 疫情影响很多小伙伴都被破离职了,下面整理了一些常见...
    WEB前端含光阅读 5,748评论 9 156
  • Vuex的五个核心概念 本文参考自Vue文档,说的非常详细,建议看文档。 Vuex是什么? VueX 是一个专门为...
    一二三四五_6ce3阅读 1,228评论 0 0
  • Vuex是什么? VueX 是一个专门为 Vue.js 应用设计的状态管理架构,统一管理和维护各个vue组件的可变...
    她说东京很热阅读 3,780评论 0 0
  • ①Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 状态管理:简单的理解就是统一管理和维护各个vue...
    翎雪_b20f阅读 774评论 0 0
  • 16宿命:用概率思维提高你的胜算 以前的我是风险厌恶者,不喜欢去冒险,但是人生放弃了冒险,也就放弃了无数的可能。 ...
    yichen大刀阅读 6,030评论 0 4