Vue 初心者筆記 #11 TodoList 修改功能

本文介紹 TodoList「修改」待辦事項內容的作法,以及動態計算還有幾筆未完成的待辦事項。

雙擊修改資料內容

STEP 1:新增雙擊事件

在原本呈現資料的地方加上 雙擊事件 @dblclick
雙擊後會觸發事件 editTodo(item) 並會傳物件進來

1
2
<li class="list-group-item" v-for="(item, key) in filteredTodos"
@dblclick="editTodo(item)">

同樣在 Vue app 也要加上 editTodo function

1
2
3
4
5
6
7
8
9
10
methods: {
addTodo: function(){...},
removeTodo: function(todo){...},

// 加上 editTodo function
editTodo: function(item){
console.log(item);
},

},

雙擊後 console 會出現物件

STEP 2:切換顯示 input

建立 Cache

首先我們要把 item 存起來
因為我們要知道目前是哪一筆資料被編輯

因此我們先新增兩個 data
並把 item 存在 cacheTodo、把標題存在 cacheTitle

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
...
data: {
newTodo: '',
todos: [
{
id: '345',
title: '妳好',
completed: false,
}
],
visibility: 'all',

// 新增兩個 data
cacheTodo: {},
cacheTitle: '',
},
methods: {
addTodo: function(){...},
removeTodo: function(todo){...},

// editTodo
editTodo: function(item){
console.log(item);
this.cacheTodo = item;
this.cacheTitle = item.title;
},

cacheTitle 會拿來做 input 預設顯示的內容

動態切換 input 與資料內容

  1. 把 input 放到 div.d-flex 的下方
  2. 利用 v-if 新增顯示條件
    如果 item.id 不等於 cacheTodo.id 就顯示完整 li
    如果 item.id 等於 cacheTodo.id 就顯示 input
1
2
3
4
5
6
7
8
9
10
<li class="list-group-item" v-for="(item, key) in filteredTodos"
@dblclick="editTodo(item)"
v-if="item.id !== cacheTodo.id">
<div class="d-flex">
...
</div>
<!-- 新增 input -->
<input type="text" class="form-control"
v-if="item.id === cacheTodo.id">
</li>

現在點擊兩下就能切換到 input 了
不過目前一次只能顯示一個 input

因為 cacheTodo 預存的資料會被替換掉
所以一次只能呈現一筆資料內容

STEP 3 編輯資料內容

  1. input 綁定 cacheTitle 資料
  2. input 新增事件:按下 ESC 取消編輯
  3. input 新增事件:按下 Enter 完成編輯
1
2
3
4
5
<input type="text" class="form-control"
v-if="item.id === cacheTodo.id"
v-model="cacheTitle"
@keyup.esc="cancelEdit"
@keyup.enter="doneEdit(item)">

取消編輯:this.cacheTodo 等於空物件
完成編輯:把預存的標題存成標題,然後把預存的標題清空,也把 cacheTodo 清空

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
methods: {
addTodo: function(){...},
removeTodo: function(todo){...},
// 編輯的物件
editTodo: function(item){
console.log(item);
this.cacheTodo = item;
this.cacheTitle = item.title;
},
// 取消編輯
cancelEdit: function(){
this.cacheTodo = {};
},
// 完成編輯
doneEdit: function(item){
item.title = this.cacheTitle;
this.cacheTodo = '';
this.cacheTodo = {};
}
},

計算還有幾筆待辦事項未完成

使用花括號呈現未完成的筆數於畫面上

1
<span>還有 {{ countLeftTodo }} 筆任務未完成</span>

計算方式的寫法與 filteredTodos 的部分有點相似

先宣告一個存放未完成 item 的陣列
然後將整個 todos 內容用 forEach 去跑

如果 item 的 completed 是 false,就把它放到 leftTodos 裡面
最後回傳 leftTodos 的長度
這個長度就是我們想呈現的未完成筆數了 :P

1
2
3
4
5
6
7
8
9
10
11
12
13
14
computed: {
filteredTodos: function(){...},

// 計算還有幾筆待辦事項未完成
countLeftTodo: function(){
let leftTodos = [];
this.todos.forEach(function(item){
if(!item.completed){
leftTodos.push(item);
}
});
return leftTodos.length;
},
},

結語

到這邊 TodoList 就算是大功告成了!
經過這次 TodoList 的練習,算是大概瞭解一些 Vue.js 的概觀與優缺點
接下來在學習 Vue 的語法細節及生命週期時,就會更容易了解這些的相關性

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