Vuex 狀態管理

專題公板模組是應公司『大量產生不同專題內容網頁』的需求而生的專案,用意是讓使用者自由拖拉預先設計好的模組、輸入模組所要呈現的內容,最後自動生成靜態網頁供外部瀏覽。

考慮到模組未來的擴充性,以及前端各模組表單欄位的重複性,我們從最小的、各種不同型態的表單輸入欄位開始製作 Vue 元件——不同的表單欄位組成一篇內容,多篇內容填滿一個模組,最後這些模組再加上一些基本設定,匯出成最終的內容網頁。

因應這樣的設計,我們將整個網頁內容的資料以 JSON 格式儲存,並透過 Vuex 統一管理狀態。各元件對各自對應的 key 值做處理,更改狀態之後,所有元件再同步渲染;這樣的單向資料流相對容易理解,未來即使需要元件間共享某些欄位也容易許多。

安裝 Vuex

使用 vuex 前先透過 npm 或 yarn 安裝:

npm

$ npm install vuex --save

yarn

$ yarn add vuex

使用 Vuex

在 app.js 或 main.js 引入並使用:

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

狀態管理流程

Vuex 的狀態管理流程可參考官網這張圖片: vuex狀態管理流程

Step1. Dispatch Actions

Vuex 的單向資料流是從 Action 開始的,當前端 Vue 元件要修改 State 時,透過 dispatch() 觸發指定 Action。

store.dispatch('definedAction', data)

而在定義的 Action 中,可以處理各種非同步請求,例如向後端伺服器打 API 獲取資料,得到後再向指定的 Mutaion 發出 Commit 要求修改 State。

注意

Action 中不可修改 State,只能執行修改前的資料獲取跟處理;State 的修改一律在 Mutations 中執行。

Step2. Commit Mutations

當 Action 處理完資料,便可以透過 commit() 修改 State。

store.coommit('definedMutaion', key, value)

在指定的 Mutation 中,更新對應的狀態值。

// ...
mutations: {
  definedMutation (state, key, value) {
    state[key] = value
  }
}

Step3. Get State

前端 Vue 元件可以透過 Getter 取得 State,首先設定 getters

getters: {
  // ...
  definedValue: (state) => {
    return state.someValue
  }
}

接著在前端元件的 computed 中讀取:

computed: {
  definedValue () {
    return this.$store.getters.definedValue
  }
}

或者透過 mapGetters 這個輔助函式讀取:

import { mapGetters } from 'vuex'

export default {
  // ...
  computed: {
    ...mapGetters([
      'definedValue',
      'anotherGetter',
      // ...
    ])
  }
}

當 State 更新之後,前端元件也會重新 Render。

Computed 的雙向綁定

在這個專案中,前端連結 State 的都是表單的輸入欄位,若將 State 直接綁定 v-model,當使用者輸入時,v-model 會試圖直接修改狀態而報錯。

原因

State 的修改只能在 Mutaion 中進行。

若要將 State 與表單欄位綁定,可參考官網這篇的作法,透過 Computed 的雙向綁定,在取值時透過 get 取值,編輯時透過 set 中發出 commit() 更新 State,再藉由 get 取得更新後的值重新刷新。

<input v-model="message">
// ...
computed: {
  message: {
    get () {
      return this.$store.getters.message
    },
    set (value) {
      this.$store.commit('updateMessage', value)
    }
  }
}
Last Updated: 7/28/2019, 6:14:16 AM