Vue 初心者筆記 #9 TodoList 刪除功能

上次做了新增待辦事項的功能,這次要來挑戰刪除待辦事項的功能。

「刪除」待辦事項

接下來我們要做的是「刪除」待辦事項的功能
就是當我們按下待辦事項右邊的叉叉之後,可以把該筆待辦事項給刪除掉

大致步驟如下:

  1. 新增函式 removeTodo
  2. 新增索引值 key 以辨別欲刪除物件
  3. 刪除陣列某一筆資料

STEP 1:新增函式 removeTodo

在 Vue app 的 methods 裡面新增 removeTodo 函式
這個 removeTodo 就是我們要做的刪除功能

1
2
3
4
5
6
7
8
9
methods: {
addTodo: function(){
... // 上次的先註解掉以節省空間
},
// 刪除功能
removeTodo: function(){
...
},
},

然後使用 v-on:click 把這個函式綁定到待辦事項的叉叉圖案上

1
2
3
<button type="button" class="close ml-auto" aria-label="Close" @click="removeTodo()">
<span aria-hidden="true">&times;</span>
</button>

STEP 2:新增索引值 key 以辨別欲刪除物件

接下來新增索引值 key,因為要知道是刪除哪個 Todo

新增 v-for索引值

1
2
3
<li class="list-group-item" v-for="(item,key) in todos">
...
</li>

v-for=”(item, key) in todos”
key 是陣列的索引位置

然後把 key 加到 removeTodo 函式中

1
2
3
4
5
6
7
8
9
methods: {
addTodo: function(){
...
},
// 刪除功能
removeTodo: function(key){
...
},
},

叉叉上用 @click 綁定的函式也要記得加上參數

1
2
3
<button type="button" class="close ml-auto" aria-label="Close" @click="removeTodo(key)">
<span aria-hidden="true">&times;</span>
</button>

STEP 3:刪除陣列某一筆資料

使用 JavaScript 的 splice() 方法,刪除陣列上的資料
splice(key, 1) 就是從索引 key 開始,往後刪除 todos 資料 1 筆

1
2
3
4
5
6
7
8
9
methods: {
addTodo: function(){
...
},
// 刪除功能
removeTodo: function(key){
this.todos.splice(key, 1);
},
},

Debug:改用 id 刪除值

刪除待辦事項時,會因為索引值的問題,導致刪除結果出現錯誤

因此我們改用每個待辦事項的 id (也就是 timestamp) 來刪除資料

STEP 1:修改傳入函式的參數

原本 removeTodo 傳入的參數是 key
把它改成 TodoList 本身

1
2
3
4
removeTodo: function(todo){
let newIndex = '';
this.todos.splice(newIndex, 1);
},

這邊的 todo 是參數名稱,可以任意取名

同樣 removeTodo 的參數也改為傳入 item 本身(也就是 todo 本身)

1
2
<button type="button" class="close ml-auto" aria-label="Close"
@click="removeTodo(item)">

STEP 2:取得正確的索引值

  1. 宣告 newIndex 存放要刪除的正確參數:let newIndex = ''
  2. 使用 forEach 確保取得的是相同的值
  3. 如果「點選物件的 id」與「當前元素的 id」相符合,就取出它的索引位置 (key):if(todo.id == item.id){ newIndex = key; }
  4. 並放到要刪除的位置上:this.todos.splice(newIndex, 1)

forEach 的部分是這樣的:
遍歷 vm.todos 陣列內的每個元素,當「點選的 id === 當前元素的 id」時
把目前跑到第幾個元素的 key 賦值給 newIndex
所以這個 key 才是索引

1
2
3
4
5
6
7
8
9
10
removeTodo: function(todo){
let newIndex = '';
let vm = this;
vm.todos.forEach(function(item, key){
if(todo.id == item.id){
newIndex = key;
}
})
this.todos.splice(newIndex, 1);
},

改良寫法

有個更精簡的寫法
findIndex 是一個比較簡單的找到索引的方式
能把回傳為 true 的索引位置存到前方的變數裡面

findIndex 是 ES6 新的陣列方法
會依據提供的測試函式,尋找陣列中符合的元素,並返回其 index(索引)

1
2
3
4
5
6
7
removeTodo: function(todo){
let vm = this;
let newIndex = vm.todos.findIndex(function(item, key){
return todo.id === item.id;
})
this.todos.splice(newIndex, 1);
},

額外去命名 let vm = this; 的原因:

在這個例子中不這麼做也可以

但是如果在 forEach 中的匿名函數中,使用 this 來存取 data 中的屬性的話,就會發生讀取不到的問題

因此為了保險起見,我們都還是會宣告一個 vm 變數,來確保存取的屬性是 Vue 實例中的 data 內的屬性

清除所有任務

最後還有一個常用的小功能
就是一鍵清除所有任務
只需要寫一行 Code 就能完成囉

1
<a href="#" @click.prevent="removeAllTodo">清除所有任務</a>
1
2
3
4
5
6
7
8
9
10
11
12
methods: {
addTodo: function(){...},
removeTodo: function(todo){...},
editTodo: function(item){...},
cancelEdit: function(){...},
doneEdit: function(item){...},

// 清除所有任務
removeAllTodo: function(){
this.todos = [];
},
},

結語

經過以上步驟與 Bug 的修正後就能完成「刪除」功能囉!
下一篇會介紹如何做出「頁籤」

以上資源是我自己整理過後的筆記,若有錯誤歡迎隨時和我聯繫。