文章

Vuex 狀態管理基礎

在大型 Vue 應用中,隨著組件之間的通信越來越複雜,管理應用的狀態(state)變得困難。這時,Vuex 提供了一種集中式的狀態管理解決方案,允許應用中的所有組件共享同一個狀態,並且遵循特定的規範來修改狀態,從而更容易管理和維護。

1. 什麼是 Vuex?

Vuex 是 Vue.js 的一個狀態管理模式與庫,它使用一個全局的 store 來存儲應用的狀態。應用中的所有組件都可以訪問這個 store 中的狀態,並且只有通過提交 mutation 的方式才能修改這些狀態。這樣的模式保證了狀態的變更是可預測且可追蹤的。


2. Vuex 的核心概念

Vuex 包含五個核心概念:StateGetterMutationActionModule

1. State(狀態)

State 是 Vuex 中的核心,儲存應用的所有共享數據。我們可以把它看作一個單一的真實數據源,所有的組件都可以從這裡讀取數據。

定義 state

1
2
3
4
5
const store = new Vuex.Store({
  state: {
    count: 0
  }
});

在組件中訪問 state

1
2
3
<template>
  <div></div>
</template>

2. Getter(取得狀態的方法)

Getter 用於從 state 中派生出一些狀態,可以理解為 Vue 的計算屬性(computed)。它們可以幫助我們從 state 中獲取處理後的值。

定義 getter

1
2
3
4
5
6
7
8
9
10
const store = new Vuex.Store({
  state: {
    count: 10
  },
  getters: {
    doubleCount: state => {
      return state.count * 2;
    }
  }
});

在組件中使用 getter

1
2
3
<template>
  <div></div>
</template>

3. Mutation(修改狀態的方法)

Mutation 是唯一能夠直接修改 state 的方式。每個 mutation 都有一個字符串類型的事件類型,以及一個回調函數。回調函數就是具體修改狀態的地方,並且它會接收 state 作為第一個參數。

定義 mutation

1
2
3
4
5
6
7
8
9
10
const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment(state) {
      state.count++;
    }
  }
});

要修改 state,需要在組件中通過 commit 方法來觸發 mutation

1
2
3
<template>
  <button @click="$store.commit('increment')">增加</button>
</template>

4. Action(異步操作與業務邏輯)

Actionmutation 類似,不同的是它們用於執行異步操作。在 action 中,我們不能直接修改 state,而是通過提交(commit)mutation 來間接修改 state

定義 action

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment(state) {
      state.count++;
    }
  },
  actions: {
    incrementAsync({ commit }) {
      setTimeout(() => {
        commit('increment');
      }, 1000);
    }
  }
});

在組件中使用 action

1
2
3
<template>
  <button @click="$store.dispatch('incrementAsync')">異步增加</button>
</template>

5. Module(模組)

隨著應用變得越來越複雜,我們可以將 Vuex 的 store 分割成多個模組(module)。每個模組都有自己的 state、mutation、action 和 getter,並且它們可以組合在一起。

定義模組:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
const moduleA = {
  state: () => ({
    count: 0
  }),
  mutations: {
    increment(state) {
      state.count++;
    }
  },
  actions: {
    incrementAsync({ commit }) {
      setTimeout(() => {
        commit('increment');
      }, 1000);
    }
  },
  getters: {
    doubleCount: state => state.count * 2
  }
};

const store = new Vuex.Store({
  modules: {
    a: moduleA
  }
});

在組件中訪問模組的 stategetter

1
2
3
4
<template>
  <div></div>
  <div></div>
</template>

3. Vuex 的工作流程

Vuex 遵循單向數據流

  1. 組件觸發 action:通過 dispatch 來發送 actionaction 負責處理異步操作或邏輯。
  2. Action 提交 mutation:當 action 完成後,它通過 commit 提交一個 mutation
  3. Mutation 修改 statemutation 是唯一可以修改 state 的途徑。
  4. State 更新後,Vue 會自動地重新渲染組件,從而更新視圖。

這種單向數據流的方式,保證了應用中狀態的可預測性和可維護性。


4. 基本範例

一個簡單的 Vuex 範例包含一個計數器,使用 Vuex 來管理狀態。

定義 Vuex store:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

export default new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment(state) {
      state.count++;
    },
    decrement(state) {
      state.count--;
    }
  },
  actions: {
    incrementAsync({ commit }) {
      setTimeout(() => {
        commit('increment');
      }, 1000);
    }
  },
  getters: {
    doubleCount: state => state.count * 2
  }
});

在組件中使用 Vuex:

1
2
3
4
5
6
7
8
9
<template>
  <div>
    <p>計數: </p>
    <button @click="$store.commit('increment')">增加</button>
    <button @click="$store.commit('decrement')">減少</button>
    <button @click="$store.dispatch('incrementAsync')">異步增加</button>
    <p>雙倍計數: </p>
  </div>
</template>

5. 總結

  • Vuex 提供了一個集中式的狀態管理系統,解決了多組件間數據共享和狀態同步的問題。
  • State 儲存應用的全局狀態,Getter 用來獲取衍生狀態,Mutation 是唯一可以同步修改狀態的方式,Action 用於處理異步操作,Module 則用來劃分和組織狀態。
  • 透過 Vuex,應用的狀態變更流程清晰且可追蹤,讓開發者可以更輕鬆地維護和擴展應用。
本文章以 CC BY 4.0 授權