# 24. TodoList 資料模組

可以試著先在 Vuex 處理資料的部分、思考資料怎麼處理,包含路由篩選資料的功能,之後再去建立畫面。

# 開啟嚴格模式

開發的時候,建議先加上 strict: true,以免不小心改到 state 而不知。

# 初始化,讀取 localStorage

  • 先進行資料的初始化,取得 localStorage (以下簡稱 LS) 原有的內容:
    • 透過 actions ,取得 LS 的資料。
    • 將讀取到的資料,commitmutationsSET_TODOS
    • SET_TODOS 將資料更新到 state 裡面的 todos
  • LS 的處理,建議另外拆分出來管理:
    • 取 (load) :將指定的 LS 資料取出,並用 JSON.parse 轉成物件。若 LS 無資料,則預設為空陣列。
    • 存 (save) :將資料更新到 LS,並先用 JSON.stringify 轉成字串。
import { createStore } from "vuex";

// 將 LS 的存取拆出來管理
const LS = {
  load() { // 取得放在 LS 裡的資料
    return JSON.parse(localStorage.getItem("vue-todo") || [])
  },
  save(data) { // 將資料儲存到 LS
    localStorage.setItem("vue-todo", JSON.stringify(data))
  }
}

export default createStore ({
  strict: true, // 開啟嚴格模式
  state: {
    todos: [
      { content: "vue-content", complete: false },
      { content: "vue-content", complete: true },
      { content: "vue-content", complete: false },
    ]
  },
  mutations: {
    SET_TODOS(state, data){ // 將 LS 回傳結果更新到 todos 
      state.todos = data
      LS.save(state.todos)
    }
  },
  actions: {
    INIT_TODOS(commit) {
      commit("SET_TODOS", LS.load()) // 讀取 LS 以初始化
    }
  }
})

# 資料的 CRUD

待辦清單有以下基本功能,這些功能都能在 mutations 處理資料,並在更新 state 後將資料存到 LS 裡面:

  • 新增事項:將新增的事項推到 todos 陣列。
  • 修改事項:將陣列中索引值為 index 的內容更新為傳入的 data
  • 刪除事項:將陣列中索引值為 index 的資料移除。
  mutations: {
    SET_TODOS(state, data){
      state.todos = data
      LS.save(state.todos)
    },
    // 新增事項
    ADD_TODO(state, data) { 
      state.todos.push(data)
      LS.save()
    },
    // 修改事項
    UPDATE_TODO(state, {index, data}) { 
      state.todos[index] = data
      LS.save()
    },
    // 刪除事項
    REMOVE_TODO(state, index) { 
      state.todos.splice(index, 1)
      LS.save()
    }
  },

但上面修改事項的寫法會有問題,之後會說明並進行修改。

# 資料的篩選

我們會透過切換路由去呈現不同狀態的資料。我們可以像 LS 那樣,在 export default 之外 ,將資料的篩選功能額外管理。

const LS = {
  // 略 ...
}

// 將篩選功能獨立出來管理
const filter = {
  all(todos) {
    return todos
  },
  active(todos) {
    return todos.filter(todo => !todo.complete)
  },
  complete(todos) {
    return todos.filter(todo => todo.complete)
  }
}

export default createStore ({
  // 略 ...
})

# getters 抓出索引值

事項的更新和刪除都需要知道其索引值,才能準確對指定事項進行操作。

  • 使用 getters 取得 statetodos 的索引值。
  • 根據所在的路由 (state.route.name),從 state.todos 篩選出符合條件的事項。
  • 將篩選後的符合事項,用 indexOf 查找其索引值,透過 map 使查找結果成為一個新的陣列。
  getters: {
    todoIndex(state) {
      return filter[state.route.name](state.todos).map(todo => state.todos.indexOf(todo))
    }
  },