# 26. TodoList 頁面模組 2 - 列表

這個小節主要說明「列表顯示」模組。

# 新增「列表顯示」模組

在 "components" 資料夾建立 "TodoListItem" 資料夾,並在裡面新增以下檔案:

  • index.vue
  • template.html

# template.html

這個模組內有這些組成:

  • <input type="checkbox"> 勾選是否完成。
  • <label> 呈現待辦事項的內容。
  • <button> 用來刪除事項。
//- components/TodoListItem/template.html

<div class="todoListItem">
  <input type="checkbox" class="toggle" v-model="complete"/>
  <label>{{ todo.content }}</label>
  <button class="destroy" @click="destroyHandler"></button>
</div>

# index.vue

  • 接收索引值
    • 使用 props 接收外部傳入的索引值 index
    • 這個模組會呈現所有待辦事項中的其中一筆,因此需要知道索引值,才能知道要呈現的是哪一筆資料。
  • 抓取該索引值內容
    • 拿到索引值後,使用 computed 抓該筆索引值的內容。
  • 刪除事項
    • 點擊 <button> 觸發 destroyHandler
    • 先確認是否要刪除,以免誤刪。
    • 如果確定,就 commit("REMOVE_TODO", this.index),刪除傳入的索引值項目。
  • 修改事項狀態 (是否完成)
    • 由於 Vuex 不能直接改 state 的資料,因次不能在 input 使用 v-model="todo.complete" 綁定並修改 todo
    • 取而代之,我們可以在 computed 建立一個變數 complete,綁定到 input 上。也就是 v-model="complete",這樣就不會直接改到 store 的內容。
    • complete 裡面會有 getset 兩個功能:
      • get 取得此索引值資料的完成狀態。
      • set 透過 commit 去更新此 store 中此筆資料的完成狀態。
    • 如果要進行修改,依據先前在 mutation 裡面寫的 UPDATE_TODO ,參數需要同時傳入索引值 index 以及整包資料 data
//- components/TodoListItem/index.vue

<script>
export default {
  props: {
    index: {
      type: Number,
      required: true
    }
  },
  computed: {
    todo(){
      return this.$store.state.todos[this.index]
    },
    complete: {
      get(){
        return this.todo.complete
      },
      set(val){
        this.$store.commit("UPDATE_TODO", {
          index: this.index,
          data: {
            content: this.todo.content,
            complete: val
          }
        })
      }
    }
  },
  methods: {
    destroyHandler(){
      if(confirm(`是否確認刪除 ${this.todo.content} ?`))
      this.$store.commit("REMOVE_TODO", this.index)
    }
  }
}
</script>

<template src="./template.html"></template>

# 使用「列表顯示」模組

同樣地,我們要在 "App.vue" 引入以使用模組。

//- App.vue

<template>
  <div id="nav">
    <router-link :to="{name: 'all'}">全部</router-link> |
    <router-link :to="{name: 'active'}">未完成</router-link> | 
    <router-link :to="{name: 'complete'}">已完成</router-link>
  </div>
  <TodoInput/>
  // 在輸入框底下用 v-for 陳列 TodoListItem
  // 記得要綁定 key,並傳入參數 index 到模組以顯示該筆資料
  <div id="list">
    <TodoListItem v-for="index in todoIndex" :key="index" :index="index"/>
  </div>
</template>

<script>
import TodoInput from "./components/TodoInput/index.vue"
import TodoListItem from "./components/TodoListItem/index.vue"

export default {
  components: {
    TodoInput,
    TodoListItem
  },
  // 略 ...
}
</script>