iT邦幫忙

2017 iT 邦幫忙鐵人賽
DAY 17
0
Modern Web

實作小範例入門 Vue & Vuex 2.0系列 第 17

vue & vuex 17 - 覺得 store 有點亂,動手拆成 modules 吧!

今天目標:

  • 自己的 store 自己整理。

目前我們所用的方法是所有 action 程式放在 actions.js 裡面。

mutations, getters 以此類推..。

所以檔案中包含著 count 與 todo 的程式,辨識的方法可能是加個註解。

如果未來功能多的時後,會不會有點難維護呢?(程式越長越長)

因此今天的目標就是利用 vuex modules 方法,來整理我們的程式。


資料結構:

官方提供這樣的結構參考:

└── store
    ├── index.js      // root 組合 modules 的地方
    ├── actions.js    // root 最外層的 action
    ├── mutations.js  // root 最外層的 mutation
    └── modules
        ├── count.js  // Count modules
        └── todo.js   // Todo modules

你也利用這樣的結構:

└── store
    ├── index.js           // root 組合所有 modules 的地方
    ├── actions.js         // root 最外層的 action 
    ├── mutations.js       // root 最外層的 mutation 可以改變所有模組的 state
    ├── getter.js          // root 最外層的 getter 可以拿到所有模組的 state
    ├── mutations_types.js // 所有 mutation key 存放的地方
    ├── count
    │   ├── index.js      // 組合 count 與 export todo 的地方
    │   ├── actions.js    // count action
    │   └── mutations.js  // count state, mutation
    ├── todo
    │   ├── index.js      // 組合 todo 與 export todo 的地方
    │   ├── actions.js    // todo action
    │   └── mutations.js  // todo state, mutation

如果用資料夾整理的方式
記得 vuex 預設會去找 index.js 因此這是最好的組裝場所。

端看團隊的選擇,與 state 的大小,可能 API 超過五隻我們就會選擇第二種方式去開發。

檔名跟結構其實官方沒有規定我們要怎麼放,只要不違反vuex 的原則

  1. 只有 mutation 可以改變 state。
  2. 非同步的事件應該在 action 處理。
  3. mutation 只能處理同步事件。

由於我們程式碼不多,所以就利用官方提供的方法來動手來整理 count 與 todo 吧!

以下只紀錄 count 的部分。


modules/count.js

/* 
  這邊可以改為用 types 物件取代 matutions_type.js (繼續用也可以)
  然後在前面加上模組名稱作為前綴,用來避免與其他模組重複。
  因為 action、mutation、和 getter 依然是註冊在全域的命名空間
*/
const types = {
  INCREASE: 'count/INCREASE',
  DECREASE: 'count/DECREASE',
  COUNT_RESET: 'count/COUNT_RESET'
}

// count state 必須是 Object
const state = {
  count: 0
}

// getters 也可以整理到這邊直接返回 count 內容
const getters = {
  getCount: state => state.count
}

// actions 也是以 Object 形式建構。
const actions = {
  actionIncrease ({ commit }, num) {
    commit(types.INCREASE, num);
  },
  actionDecrease ({ commit }, num) {
    commit(types.DECREASE, num);
  },
  actionCountReset ({ commit }) {
    commit(types.COUNT_RESET);
  }
}

// mutations
const mutations = {
  [types.INCREASE] (state, num) {
    state.count += num;
    console.log('newINCREASE', num, 'state?', state.count);
  },
  [types.DECREASE] (state, num) {
    state.count -= num;
    console.log('newDECREASE', num, 'state?', state.count);
  },
  [types.COUNT_RESET] (state) {
    state.count = 0;
    console.log('newCOUNT_RESET - state?', state.count);
  }
}

/*
  因為我們把 vuex 所有職權都寫在同一隻檔案,
  所以必須要 export 出去給最外層 index.js 組合使用
*/
export default {
  state,
  getters,
  actions,
  mutations
}

types

index.js (root)

import Vue from 'vue';
import Vuex from 'vuex';
// root
import * as getters from './getters.js';
// modules
import count from './modules/count';
import todo from './modules/todo';

Vue.use( Vuex );

export default new Vuex.Store({
  // root
  getters,
  // 將整理好的 modules 放到 vuex 中組合
  modules: {
    count,
    todo
  },
  // 嚴格模式,禁止直接修改 state
  strict: true
});

整理成 modules 與原本寫在 root 有什麼不同?


寫在 root 中的 store:

state: {
  count: 0,
  todo: [ .. ]
}

整理成 modules 的 store:

state: {
  count: {
    count: 0
  }
  todo: {
    todo: [ .. ]
  }
}

多包了一層!為什麼?


我們在 index.js (root) 是怎麼組合的?

import count from './modules/count';

export default new Vuex.Store({
  modules: {
    count: count
// modules name: value
  }
});

那 modules/count 是怎麼組合的呢?

const state = {
  count: 0
}

因此最後的組合就會變成這樣囉:

state: {
  count: {
    count: 0
  }
}

整理成 modules 的好處是:

相關 state 自成一國,假這我有 user 有關的狀態操作,可以全部寫在一起。

我在 gettermutations 操作的時候,就不需要一層一層的去找我的 state

從 root 的話我們可以能要return state.user.user.username

包裝 modules 我只要針對 return state.user.username 去操作就可以了。

不管是命名,或是操作 state 都會變得更扁平,更直覺。

那要怎麼拿到其他 modules 的 state

如果要取得或改變其他 modules 的狀態,你必須將程式設計在 root 那層。如 gettermutations

getter.js

// get count & todo
export const getCountandTodo = state => {
  return {
    count: state.count.count,
    todo: state.todo.todos,
  }
}

// just return all state
export const getAllstate = state => state

取得 state 示意圖:

vuex state & modules state

命名空間

不管是在 root 或是 modules 所有 action、mutation、和 getter 依然是註冊在全域的命名空間,因為 store 只有一個。


github 完整範例:

實作小範例入門 Vue & Vuex 2.0 - github 完整範例

使用 git checkout 切換每天範例。


上一篇
vue & vuex 16 - 自訂按鈕 custom checkbox ($emit, $on)
下一篇
vue & vuex 18 - 開發小技巧
系列文
實作小範例入門 Vue & Vuex 2.030

尚未有邦友留言

立即登入留言