分類
Vue 出一個電商網站

第 3 節: 製作一個 Todo List 來小試身手吧

作業模板:


22. 套用版型及建立代辦事項列表的資料

製作步驟:

  1. 在 HTML 的 <li> 列表內加入:v-for=”item in todos”
  2. 在 HTML 的 <input> 輸入格內加入:v-model=”newTodo”
  3. 在 HTML 的 <button> 按鈕內加入:@click=”addTodo”
  4. 在 Vue app 物件裡包含的 data 物件內加入 newTodo 項目,並賦予它空白字串,完成後會像這樣:newTodo: “”
  5. 接著,在 data 物件內加入 todos 空白陣列,用來呈現待辦事項內容,完成後會像這樣:todos: []
  6. 在 Vue app 物件裡新增 methods 項目,在該項目的物件裡面新增 addTodo 項目,並賦予它一個函數,完成後會像這樣:addTodo: function () {}
  7. 在 todos 陣列內加入一個物件,並給這個物件三個項目:id、title、completed。其中 id 跟 title 為字串資料,completed 為布林值[1]
  8. 把 HTML <input> 核取方塊的 id 修改成 :id=”item.id” (: 是 v-bind 的意思)。在 <label> 標籤內加入 :for=”item.id” 屬性,並在包著的地方加入 {{ item.title }},來顯示 todos 陣列內的物件存放的項目。
  9. 在相同的 <input> 標籤內加入 v-model=”item.completed” 屬性,核取方塊被勾選以後,completed 項目就會被轉換為 true。
  10. 回到 methods 裡面的 addTodo 函數。宣告一個變數 value 並指派 newTodo 給它[2]
  11. 宣告一個變數 timestamp 並指派給它目前的時間的整數[2]
  12. 將 value、timestamp 以及 completed: false 布林值推送至 todos 陣列內[2]
  13. 在 addTodo 函數外加入 this.newTodo = ”;。當 addTodo 函數被執行過以後就清空 newTodo 輸入欄位[2]
  14. 在 <input> 欄位加入 @keyup.enter=”addTodo” 屬性。在輸入欄位輸入完值以後,就可以用按下 Enter 的方式來新增資料到 todos 陣列內。

[1] todos 示範資料

todos: [
{
    id: '1',
    title: '妳好',
    completed: false
}],

[2] addTodo函數內容

addTodo: function () {
    var value = this.newTodo;                     //10
    var timestamp = Math.floor(Date.now());       //11
    this.todos.push({                             //12
            id: timestamp,
            title: value,
            completed: false
        });
        this.newTodo = '';                        //13
}

23. 刪除陣列上的特定資料

製作步驟:

  1. 在 addTodo 函數內加入當 newTodo 沒有數值時就不回傳任何資料的功能[1]
  2. 將指派給 value 變數的 newTodo 加上會自動消除空白的功能。
  3. 在 HTML 內的 <li> 標籤所含的 <button> 內加入 @click=”removeTodo” 屬性。
  4. 在 methods 加入 removeTodo 項目,並指派一個函數給它[2]
  5. 修改 <li> 的 v-for 屬性為: v-for=”(item, key) in todos”,以取得 todos 陣列的索引序數。
  6. 修改 <li> 標籤內的 @click=”removeTodo” 屬性為:@click=”removeTodo(key)”。

[1] 當 newTodo 沒有輸入數值,addTodo 就不回傳值

addTodo: function () {
    var value = this.newTodo.trim();            //2
    var timestamp = Math.floor(Date.now());
    if (!value) {                               //1
        return;
    }
    this.todos.push({
            id: timestamp,
            title: value,
            completed: false
        });
        this.newTodo = '';
}

[2] removeTodo 函數內容

removeTodo: function (key) {
    this.todos.splice(key, 1);
}

24. 製作頁籤分類的功能

製作步驟:

  1. 在 <label> 標籤內加入 :class=”{‘completed’, item.completed}”。當 todos 陣列內所含的物件的 completed 項目被打勾(狀態變成 true)時,套用 class 到 <label> 包著的文字上。
  2. 在 todos 陣列之後新增一個變數 visibility: ‘all’。
  3. 將帶有 nav-link Class 的 <a> 標籤內的 active Class 刪除。
  4. 在帶有「全部」字樣的 <a> 標籤內加入 :class=”{‘active’, visibility == ‘all’}” 屬性以及 @click=”visibility == ‘all'” 屬性。
  5. 在帶有「進行中」字樣的 <a> 標籤內加入 :class=”{‘active’, visibility == ‘active’}” 屬性以及 @click=”visibility == ‘active'” 屬性。
  6. 在帶有「已完成」字樣的 <a> 標籤內加入 :class=”{‘active’, visibility == ‘completed’}” 屬性以及 @click=”visibility == ‘completed'” 屬性。
  7. 在 methods 物件之後新增一個 computed 物件。
  8. 在 computed 內新增一個方法,命名為 filteredTodos,並指派一個函數給它[1]
  9. 將 <li> 標籤內的 v-for 所含的 todos 更改為 filteredTodos。這樣列表上顯示的項目都會是經由 filteredTodos 函數過濾後的 todos 陣列。

[1] filteredTodos 函數內容

filteredTodos: function () {
    if (this.visibility == 'all') {
            return this.todos;
        } else if (visibility == 'active') {
                var newTodos = [];
                this.todos.forEach(function (item) {
                    if (!item.completed) {
                        newTodos.push(item);
                      }
                })
                return newTodos;
        } else if (visibility == 'completed') {
                var newTodos = [];
                this.todos.forEach(function (item) {
                    if (item.completed) {
                        newTodos.push(item);
                      }
                })
                return newTodos;
}

25. 雙擊修改資料內容

製作步驟:

  1. 在 <li> 標籤內加入屬性 @dblclick=”editTodo(item)”。
  2. 在 methods 物件內加入一個 editTodo 項目並賦予一個函數給它[1]
  3. 在 todos 陣列之後加入 cacheTodo: {} 以及 cacheTitle: ”。用來暫存在修改資料時的 todos 物件以及文字內容。
  4. 把用來修改 title 的 <input> 欄位給取出來,改放到帶有 d-flex Class 的 <div> 標籤的下方。
  5. 在帶有 d-flex 的 <div> 標籤內加入 v-if=”item.id !== cacheTodo.id” 屬性。
  6. 在 <input> 標籤內加入 v-if=”item.id === cacheTodo.id” 屬性。當雙擊列表上的 title 後,cacheTodo.id 就會等於 item.id,進而顯示出這邊的 <input> 輸入欄位。
  7. 在 <input> 標籤內加入 v-model=”cacheTitle” 以及 @keyup.esc=”cancelEdit()” 屬性。
  8. 在 methods 內加入 cancelEdit 項目並賦予一個函數給它[2]
  9. 在 <input> 標籤內加入 @keyup.enter=”doneEdit(item)” 屬性。
  10. 在 methods 內加入 doneEdit 項目並賦予一個函數給它[3]

[1] editTodo 函數內容

editTodo: function(item) {
    this.cacheTodo = item;
    this.cacheTitle = item.title;
}

[2] cancelEdit 函數內容

cancelEdit: function() {
    this.cacheTodo = {};
}

[3] doneEdit 函數內容

doneEdit: function(item) {
    item.title = this.cacheTitle;
    this.cacheTitle = '';
    this.cacheTodo = {};
}

26. 刪除項目補充說明

製作步驟:

  1. 在 removeTodo 項目內的函數內宣告一個 newIndex 函數,並賦予它空值[1]
  2. 把 removeTodo 函數內的參數從 key 改變為 todo[1]
  3. 將 <button> 標籤內的 @click=”removeTodo(key)” 修改為 @click=”removeTodo(item)”。
  4. 在 removeTodo 函數內宣告 vm 變數並賦予它 this (這個 Vue 應用程式)[1]
  5. 在宣告 vm 後再加上 vm.todos.forEach(function {})[1]

[1] 修改後的 removeTodo 函數

removeTodo: function (todo) {                    //2
    var newIndex = '';                           //1
    var vm = this;                               //3
    vm.todos.forEach(function(item, key) {       //4
        if (todo.id === item.id) {
                newIndex = key;
                }
        })
        this.todos.splice(newIndex, 1);
}

作業成品

網站連結:

http://vue-todo.wolfpackportfolio.com/

GitHub 數據庫連結:

https://github.com/happyloa/Vue.js-Todo-list

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *