zoukankan      html  css  js  c++  java
  • vuex 源码分析(六) 辅助函数 详解

    对于state、getter、mutation、action来说,如果每次使用的时候都用this.$store.state、this.$store.getter等引用,会比较麻烦,代码也重复和冗余,我们可以用辅助函数来帮助我们生成要的代码,辅助函数有如下四个:

        mapState(namespace, map)        ;用于获取state
        mapGetters(namespace, map)       ;用于获取getters
        mapMutations(namespace, map)      ;用于获取mutations
        mapActions(namespace, map)          ;用于获取actions

    每个辅助函数都可以带两个参数:

      namespace     ;命名空间,也就是模块名

      map       ;要获取的信息

    map有两种用法,可以是对象(键名是当前Vue实例设置的变量名,值是从store要获取的变量名)或者字符串数组(此时获取和设置的变量名为同一个)。

    注:使用辅助函数需要在根节点注入store

    ps:很多新手可能只会使用辅助函数,不知道还可以用this.$store.state,this.$store.getter这些用法...

    这些辅助函数返回的都是一个对象,我们可以配合ES6的对象展开运算符,我们可以极大地简化写法,例如:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
        <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
        <script src="https://unpkg.com/vuex@3.1.0/dist/vuex.js"></script>
    </head>
    <body>
        <div id="app">
            <p>{{no}}</p>
            <p>{{No}}</p>
            <button @click="test1">测试1</button>
            <button @click="test2">测试2</button>
        </div>
        <script>
            const store = new Vuex.Store({
                state:{no:100},
                getters:{
                    No:function(state){return state.no+100}
                },
                mutations:{
                    increment(state,payload){state.no+=payload.no;}
                },
                actions:{
                    increment({commit},info){
                        setTimeout(function(){
                            commit('increment',info)
                        },500)
                    }
                }
            })
            var app = new Vue({
                el:"#app",
                store,
                computed:{
                    ...Vuex.mapState(['no']),
                    ...Vuex.mapGetters(['No'])
                },
                methods:{
                    ...Vuex.mapMutations(['increment']),
                    ...Vuex.mapActions({increment1:"increment"}),
                    test1(){
                        this.increment({no:100})
                    },
                    test2(){
                        this.increment1({no:200})
                    }
                }
            })  
        </script>
    </body>
    </html>

    writer by:大沙漠 QQ:22969969

    我觉得吧,如果用到的vuex里的属性比较多还好一点,如果只用到一个state还不如用this.$store.state来获取呢,毕竟在node环境下还需要import{mapState} from 'vuex'来获取导出的符号,可以看页面具体的需求选择合理的方法。

    源码分析


     vuex内的所有辅助函数格式都一样,都是执行一个normalizeNamespace()函数,并传入一个匿名函数,该匿名函数带有两个参数,分别是namespace和map,以mapState为例,如下:

    var mapState = normalizeNamespace(function (namespace, states) {        //state辅助函数 name:命名空间 states:比如:count2: "count"
      var res = {};
      normalizeMap(states).forEach(function (ref) {                             //将states转换为对象格式,例如:[{key:count2,val:count}]
        var key = ref.key;
        var val = ref.val;
    
        res[key] = function mappedState () {                                      //计算属性对应的是一个函数,该函数内的this指向的是Vue实例
          var state = this.$store.state;                                              //获取state对象
          var getters = this.$store.getters;                                          //获取getters对象
          if (namespace) {
            var module = getModuleByNamespace(this.$store, 'mapState', namespace);
            if (!module) {
              return
            }
            state = module.context.state;
            getters = module.context.getters;
          }
          return typeof val === 'function'                                        
            ? val.call(this, state, getters)                                      //state是函数时的逻辑,获取子模块的state会执行到这里
            : state[val]                                                          //返回state[val],也就是值
        };
        // mark vuex getter for devtools
        res[key].vuex = true;
      });
      return res
    });

    normalizeNamespace是统一的一个入口,用于格式化所有的辅助函数,如下:

    function normalizeNamespace (fn) {                          //返回一个匿名函数,需要两个参数,分别是命名空间和映射,参数1可以省略
      return function (namespace, map) {
        if (typeof namespace !== 'string') {                          //如果参数1不是字符串(即忽略了命名空间)
          map = namespace;                                              //则修正参数1为map
          namespace = '';                                               //重置命名空间为null
        } else if (namespace.charAt(namespace.length - 1) !== '/') {
          namespace += '/';
        }
        return fn(namespace, map)                                     //最后执行fn函数
      }
    }

    其它几个辅助函数都差不多,就是传给normalizeNamespace的函数内实现略有不同。

  • 相关阅读:
    从零开始学Oracle—约束(三)
    ewebeditor安全解决方案 j神
    12款很棒的浏览器兼容性测试工具推荐 j神
    文件无法删除,找不到指定文件-解决办法 j神
    如何应对Global.asa木马 j神
    2012年最佳免费网站和移动应用 PSD 界面素材揭晓 j神
    PHP上传RAR压缩包并解压目录 j神
    数据库查询语句:left join ... on ... j神
    js 与或运算符 || && 妙用 j神
    实时监听输入框值变化的完美方案:oninput & onpropertychange j神
  • 原文地址:https://www.cnblogs.com/greatdesert/p/11430122.html
Copyright © 2011-2022 走看看