跳到主要內容
其他筆記

Vuex 上課筆記:用一個 todos 範例串起 state、mutation、action

上課時做的 Vuex 練習筆記,用一個從 API 載入 todo 清單、存進 store、在元件裡用 mapState 與 mapActions 取用的完整範例,把 state/mutation/action 三個概念串成一個真的能動的流程。完整的 Vuex 概念解說與 Pinia 比較已經整理在另一篇。

W

Vuex 的核心概念——state(狀態)、mutation(提交更改)、action(觸發非同步動作)、getter(取得狀態)——已經整理在《Pinia 與 Vuex:差在哪、怎麼選、怎麼寫》,這篇是上課時做的練習筆記,用一個實際會動的 todos 範例,把那幾個概念串成一個完整流程,留著當個練習紀錄。

Store 設定

export default new Vuex.Store({
  state: {
    todos: [],
  },
  mutations: {
    setTodos(state, value) {
      state.todos = value;
    },
  },
  actions: {
    loadTodos(context) {
      axios.get('https://jsonplaceholder.typicode.com/todos').then((res) => {
        context.commit('setTodos', res.data);
      });
    },
  },
});

流程是:action 負責打 API(非同步動作),拿到資料後呼叫 commit 觸發 mutationmutation 才是真正改動 state 的地方——這正是 Vuex 規定「非同步的事情放 action、真正改狀態的動作放 mutation」的實際運作樣子。

元件裡使用

<script>
import { mapState, mapMutations, mapActions } from 'vuex';

export default {
  computed: {
    ...mapState(['todos']),
  },
  mounted() {
    this.loadTodos(); // 一開始先呼叫載入
  },
  methods: {
    ...mapMutations(['setTodos']),
    ...mapActions(['loadTodos']),
  },
};
</script>

<template>
  <div>
    <h2>{{ $store.state.todos }}</h2>
    <ul>
      <li v-for="post in todos" :key="post.id">{{ post.id }}</li>
    </ul>
  </div>
</template>

{{ $store.state.todos }} 是直接存取 store 的寫法,...mapState(['todos']) 展開後則變成 computed 屬性可以直接用 todos 這個名字取用——兩種寫法效果一樣,mapStatemapMutationsmapActions 這三個輔助函式的用途,就是把 store 的東西映射到元件裡,用起來像一般的 computedmethods

搭配路由參數做篩選

<script>
import { mapState, mapMutations, mapActions } from 'vuex';

export default {
  computed: {
    ...mapState(['todos']),
    todoId() {
      return this.todos.filter((todo) => todo.userId == this.$route.params.num);
    },
  },
  mounted() {
    this.loadTodos();
  },
  methods: {
    ...mapMutations(['setTodos']),
    ...mapActions(['loadTodos']),
  },
};
</script>

<template>
  <div>
    <p>you enter by id todos {{ todoId }}</p>
  </div>
</template>

todoId 是一個 computed,依賴 todos(store 的狀態)跟 $route.params.num(路由參數),任何一個變動都會重新計算——這就是為什麼「取得符合某個條件的資料」通常會寫成 computed 而不是在 mounted 裡算一次就結束,資料來源一變,畫面才會自動跟著更新。

參考資料

分享這篇