Day 19:有名模组,无限辅助-Vuex Modules、Map Helper

前两篇介绍完 Vuex 的核心概念,最後当中大型专案需要组织较为复杂的资料结构时,总不可能一个 index.js 就塞满所有资料量,这会造成取用和管理上的不便,因此势必得经过一番模组化,将过於庞大的资料分门别类,同时搭配使用 Map Helpers 来简化冗长程序码。

Modules 有名模组

  • 将 Store 分割成多组 module,每个 module 内部各自拥有其自己的 state、getter、mutation、action。

    // member.js
    export default ({
      namespaced: true,
      state: { ... },
      mutations: { ... },
      actions: { ... },
      getters: { ... }
    })
    
    // store/index.js
    import member from './member.js'
    import Vue from 'vue'
    import Vuex from 'vuex'
    
    Vue.use(Vuex)
    export default new Vuex.Store({
      modules: {
        member,
    		...
      }
    })
    
  • 在 module 内部设定 namespaced: true,使其成为带有指定名称的 module,当 module 被注册之後,其内部拥有的所有注册路径也会跟着调整命名,取用时也能迅速得知模组来源。

    store.state.member.name
    store.getters["member/name"]
    
  • 访问全域资料:

    • 模组化的 getters 函式,可取用的参数依序为 stategettersrootStaterootGetters

      • 前两个为模组内的 state 和 getters
      • 後两个显示结果相当於 Vuex.Store 实例属性 store.statestore.getters,差别在於 Vuex.Store 实例属性为唯读状态
      // root.js
      state: {
      	number: 20
      }
      
      // member.js => module name: member
      state: {
      	name: 'John'
      }
      getters: {
      	name: state => state.name,
      }
      
      // test.js => module name: test
      getters: {
      	rootNumber: (state, getters, rootState) => rootState.number,
      	memberName: (state, getters, rootState, rootGetters) => 
              rootGetters['member/name']
      }
      
      console.log(this.$store.getters["test/rootNumber"]) // 20 
      console.log(this.$store.getters["test/memberName"]) // John
      
    • dispatchcommit 的第三个可选参数(options?: Object)若设定为 { root: true },则可跨域取用命名模组的 root actions 或 root mutations。

      // member.js => module name: member
      actions: {
          getName: {...},
      }
      
      // test.js
      actions: {
          getAllData(context): {
              context.dispatch("member/getName", null, { root: true });
      	},
      }
      
    • 注册为全域 action:在 action 内设定 { root: true },并将 action 函式定义为 handler,便能在全域中使用 dispatch 呼叫该 action。

      // member.js => module name: member
      actions: {
          getMemberName: {
            root: true,
            handler(context, payload) {...},
          },
      }
      
      store.dispatch("member/getMemberName"); // 非全域 action
      store.dispatch("getMemberName"); // 设定 root: true 注册为全域 action
      

Map Helpers 无限辅助

初学时总会先使用最基本的语法来取用 Vuex 资料:

computed:{
	name(){
		return this.$store.getters["member/name"];
	}
}

然而一旦取用的资料愈来愈多,并且资料皆来自不同的模组时,取用过程便会变成一长串重复又冗长的内容,因此 Map Helpers 正是解决困扰的重要帮手,四个核心概念各有所属的 Helper 物件——mapStatemapGettersmapMutationsmapActions,透过物件展开运算符(Object Rest/Spread Properties for ECMAScript)简化程序码。

首先需将 Helper 引入:

import { mapGetters } from 'vuex'

mapGetters

  1. 阵列写法:应用於单层结构

    computed: {
      ...mapGetters(['name','age','address','birth', ...])
    }
    
  2. 物件写法:应用於模组化 Store

    • 可以为 getter 重新命名:

      computed: {
        ...mapGetters({
          memberAge: 'member/age',
          memberName: 'member/name',
        })
      }
      // this.$store.getters["member/name"] 变成 this.memberName
      
    • 相同模组的 getter 可以提取出模组名称:

      computed: {
        ...mapGetters('member',{
          memberAge: 'age',
          memberName: 'name',
        })
      }
      
      
  3. 物件结合阵列写法:已提取模组名称,但无命名需求,则可结合阵列形式更为精简

    computed: {
      ...mapGetters('member',['age','name'])
    }
    
    

mapMutationsmapActions

在 methods 中使用 mapMutationsmapActions,两者也都可以带入 payload 参数。

import { mapMutations, mapActions } from 'vuex';

methods: {
  ...mapMutations({
		books: 'bookList',
		// this.$store.commit('bookList') 变成 this.books()
	})

  ...mapActions(['fetchBookList', 'fetchBook']), 
		// this.$store.dispatch('fetchBookList') 变成 this.fetchBookList()
		// this.$store.dispatch('fetchBook', ISBNId) 变成 this.fetchBook(ISBNId)
}

因为若一律透过 getter 取用 state,基本上就比较少有透过 mapState 取用 state 的机会,因此本篇就先略过介绍了,有兴趣的话也可以读 Vuex 文件「The mapState Helper」了解,用法上应该大同小异。

参考资料


<<:  【DAY 22】Algorithm - Insertion sort 插入排序法

>>:  Day 21:贪婪演算法(greedy algorithm)

(特别篇)统计学的陷阱区,用资料绘制盒须—爬虫D3做成D3(下)

前言 本日主要内容包含另一个网路撷取资料方式Convert HTML Tables To JSON、...

Python & SQLALchemy 学习笔记_新增、修改以及删除资料

前一篇文章有提到该如何利用 SQLALchemy 建立一张资料表, 这篇文章主要是纪录该如何利用 S...

Day 18 prototype 配色与精稿绘制

来找设计师一起 side project,前後端 / UIUX 皆可ㄛ。配对单连结: https:...

Day 29:专案07 - 天气小助理03 | Heroku云端平台

图片来源:https://www.lohaslife.cc/archives/18537 昨天最後...

利用axois来下载档案

前言: 最近公司专案上刚好碰到制作汇出报表模组开发,而过往我都是透过form submit方式直接将...