前言

Vuex 是 Vue.js 的一種狀態管理模式(工具),其他前端框架也有類似的管理工具,用來解決多個元件共用資料導致資料流混亂的問題,參考一的動圖解釋雖然是以 Redux 為例,但清楚的說明了狀態管理的使用情境。 資料流

參考

  1. 四張動圖解釋何時該用Redux
  2. Vuex官方文件
  3. Vuex語法表
  4. EventBus

概述

Vuex流程圖 下方以 Counter 舉例,大概看一下應該會發現跟原本的 Vue 差不多,也是有 data、methods、computed,只是在 Vuex 裡改叫 state、mutations、getters,還多了跟 emit 很像的 actions 屬性。

// src/store/index.js
const store = new Vuex.Store({
  state: {
    count: 0,
  },
  getters: {
    count: (state) => state.count,
  },
  mutations: {
  	incrementMutation: (state) => state.count++,
    decrementMutation: (state) => state.count--,
  },
  actions: {
    incrementAction: ({ commit }) => commit('incrementMutation'),
    decrementAction: ({ commit }) => commit('decrementMutation'),
  }
})

// template
const Counter = {
  template: `
    <div id="counter">
      <p>
        {{ count }}
      </p>
      <p>
        <button @click="increment">+</button>
        <button @click="decrement">-</button>
      </p>
    </div>
  `,
  computed: {
    count() {
      return this.$store.getters.count;
    },
  },
  methods: {
    increment() {
      this.$store.dispatch('incrementAction');
    },
    decrement() {
      this.$store.dispatch('decrementAction');
    },
  }
}

Codepen範例 Vuex 的狀態管理模式定義了資料流(Data Flow)

  1. 從圖片左邊的 View 開始,點擊加號按鍵觸發 methods.increment,發出 dispatch 的請求
  2. dispatch 的請求進到 Vuex 裡的 actions.incrementAction 再發出 commit 的請求
  3. commit 的請求進到 mutations,此時 incrementMutation 才會實際去做更新 state 的動作
  4. 接著 getters.count 監聽到 state.count 的改變,template 裡的 computed.count 監聽到 getter.count 的改變,之後 view 顯示的計數才完成 +1 的動作。

流程圖中還有兩個灰色的格子,其中一個是在 actions 上延伸的 Backend API,在 Counter 範例中沒講到單純是範例過於簡單,之後的範例會用到,簡單說明為何發 API 必須寫在 actions,因為 Vuex 其實在流程上很寬鬆,它只是一個模式,像是 Counter 範例可以再簡單一點,觸發 methods.increment 時,傳到 mutations.incrementMutation 或是直接改 state.count,程式都可以執行,實際要怎麼用,都看自己。

雖然 Vuex 流程寬鬆,但最低至少要遵守以下三點

  1. 應用層級的狀態應集中到單個 store
  2. 只能藉由 mutation 更改 state,且必須同步(不能包含異步操作)
  3. 異步操作都在 action 處理

其他下一篇再說,理論上會是輕鬆的語法篇。