Vue 初心者筆記 #10 TodoList 頁籤過濾功能

這篇也是介紹 Todo List 的製作流程,本文將介紹頁籤的作法。

刪除線效果

STEP 1:新增 CSS 樣式

在 .completed 新增刪除線樣式

1
2
3
.completed {
text-decoration: line-through;
}

STEP 2:v-model 綁定資料

單選的 Checkbox 用 v-model 綁定後
原本的 false 打勾後會變成 true

1
2
<input type="checkbox" class="form-check-input" :id="item.id"
v-model="item.completed">

STEP 3:動態切換 className

打勾後 item.completed 的變動 = 動態加入 className

前面 className 建議用字串格式來寫

1
2
3
4
<label class="form-check-label" :for="item.id"
:class="{'completed': item.completed}">
{{ item.title }}
</label>

頁籤切換效果

STEP 1:新增變數 visibility

新增一個變數叫做 visibility
表示目前呈現哪一個頁籤
這邊先填入 all 代表預設顯示的頁籤是全部內容的頁籤

1
2
3
4
5
6
7
8
9
10
var app = new Vue({
el: '#app',
data: {
newTodo: '',
todos:
// 新增變數
visibility: 'all',
},
methods: {...},
});

STEP 2:使用 :class 判斷式新增 active

BS4 的 nav-link 如果有 active 這個 class
畫面上就會呈現外框,表示目前的 Tab 是哪一個

先把它刪除,我們自己新增 :class

前面是變數名稱 ‘active’
後面是判斷式 visibility == ‘all’

變數 visibility 的值如果是 all,”全部”這個頁籤就會啟動 active 的狀態

1
2
3
4
<a class="nav-link" href="#"
:class="{'active': visibility == 'all'}">
全部
</a>

複製此效果到其他兩個頁籤
值改成 active(進行中) 與 completed(已完成)
:class="{'active': visibility == 'active'}"
:class="{'active': visibility == 'completed'}"

STEP 3:加上切換條件

接著加上切換條件 @click="visibility = 'all'"

注意這邊的 visibility = ‘all’ 只有一個等號

同樣將效果套用到其他兩個頁籤上
值改成 active(進行中) 與 completed(已完成)

補充:在 @click 加上 .prevent,可解決點擊後畫面跑到最上方的問題

頁籤範例程式碼

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<li class="nav-item">
<a class="nav-link" href="#"
:class="{'active': visibility == 'all'}"
@click.prevent="visibility = 'all'">
全部
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#"
:class="{'active': visibility == 'active'}"
@click.prevent="visibility = 'active'">
進行中
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#"
:class="{'active': visibility == 'completed'}"
@click.prevent="visibility = 'completed'">
已完成
</a>
</li>

因此,點擊”已完成”頁籤時,visibility 的值會等於 completed
同時也觸發了「加上 active 這個 className」的條件 (visibility == ‘completed’)

這邊就完成切換頁籤的功能了

資料過濾

完成頁籤切換後,資料還沒有辦法切換
因為資料還沒有做「過濾」

STEP 1:宣告 filteredTodos 方法

目前呈現資料是用 todos (原始資料)
而我們要呈現的應該是過濾後的資料

因此我們在 methods 下面再新增一個 computed
並宣告一個方法 filteredTodos

1
2
3
4
computed: {
filteredTodos: function(){
return this.todos;
},

並把 filteredTodos 替換上來

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

完成後,我們之後運用的資料就是 filteredTodos 的資料
也就是經過「過濾後」的資料

STEP 2:過濾資料 - 「全部」頁籤

呈現 visibility 為 ‘all’ 的物件

當 visibility == ‘all’ 的時候,回傳 todos
否則回傳空陣列

1
2
3
4
5
6
7
8
9
computed: {
filteredTodos: function(){
if(this.visibility == 'all'){
return this.todos;
}else{
return [];
}
}
},

完成這個步驟後,”進行中” 與 “已完成” 就沒有資料了

因為 visibility 不是 ‘all’ 的 filteredTodos 物件
都變成一個一個空陣列的物件了

STEP 3:過濾資料 - 「進行中」頁籤

呈現 visibility 為 ‘active’ 的物件

在 visibility == ‘active’ 的情況下
先宣告一個空陣列 newTodos
let newTodos = [];
預計用來接收 todos 裡面沒有完成的資料內容

接著從 todos 裡面找出未完成的資料(使用 forEach
假設這個 item 的 completed 是 “未完成” 的
就把這個 item 新增到 newTodos 裡面(使用 **push()**)

最後 return newTodos 呈現結果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
computed: {
filteredTodos: function(){
if(this.visibility == 'all'){
return this.todos;
}else if(this.visibility == 'active'){
let newTodos = [];
this.todos.forEach(function(item){
if(!item.completed){
newTodos.push(item);
}
});
return newTodos;
}
}
},

STEP 4:過濾資料 - 「已完成」頁籤

呈現 visibility 為 ‘completed’ 的物件

假設 visibility 是 completed 的情況下
else if(this.visibility == 'completed'){}

如果這個 Todo 是 “已完成” 的話,就把資料加進來
if(item.completed){ newTodos.push(item); }

最後回傳結果
return newTodos;

範例程式碼

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
27
28
computed: {
filteredTodos: function(){
// 全部
if(this.visibility == 'all'){
return this.todos;

// 進行中
}else if(this.visibility == 'active'){
let newTodos = [];
this.todos.forEach(function(item){
if(!item.completed){
newTodos.push(item);
}
});
return newTodos;

// 已完成
}else if(this.visibility == 'completed'){
let newTodos = [];
this.todos.forEach(function(item){
if(item.completed){
newTodos.push(item);
}
});
return newTodos;
}
}
},

結語

這樣子頁籤切換功能就完成囉!
下一篇會介紹如何修改已新增的待辦事項內容

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