iT邦幫忙

2017 iT 邦幫忙鐵人賽
DAY 20
0
Modern Web

30 天 Progressive Web App 學習筆記系列 第 20

Day 20 - 30 天 Progressive Web App 學習筆記 - To-Do List 實作 PWA - (新增/修改/刪除待辦事項清單)

接續昨天的範例,我們今天來完成 To-Do List 的功能實作吧!

To-Do List 需求

昨天的文章已經完成『顯示待辦事項清單』,今天要執行的是新增/修改/刪除待辦事項清單,本範例使用純 js 的方式來完成。

先複習一下今天的要執行需求以及對應的 API:


新增待辦事項

我們大概會有以下幾個步驟

  • 抓取需要的 DOM 物件(input)
  • 監聽 input 的 keydown(enter) 事件
  • 當 keydown(enter) 事件觸發時,發送 HTTP Request(POST)
  • 當 HTTP Response 時,更新畫面

抓取需要的 DOM 物件(input)

因為我們需要 input 輸入的內容,所以這裡宣告 todoInputDOM 來存放 input 的 DOM 物件。

const todoInputDOM = document.getElementById('todoInput');

監聽 input 的 keydown(enter) 事件

當使用者輸入待辦事項並按下 Enter 之後,我們要抓取 todoInputDOM 的 value。

todoInputDOM.addEventListener('keydown', event => {
    if (event.keyCode === 13 && event.target.value) {
        // 在這裡新增待辦項目...
        event.target.value = '';
    }
});

這裡監聽 todoInputDOM 的 keydown 事件,當 event.keyCode 等於 13 的時候,代表使用者按下 Enter,新增待辦項目並清空輸入框。

建立待辦項目的方法

建立一個函式,名稱為 newItem,傳入使用者輸入的文字並返回待辦項目的物件,物件內包括待辦事項 isComplete 狀態和 desc 文字。

const newItem = value => ({ desc: value, isComplete: false});

補充:

const newItem = value => { return {name: value, isComplete: false} };  

// 可以簡化為:
const newItem = value => ({ desc: value, isComplete: false});  

建立新增待辦事項的方法(POST)

http://localhost:3000/todolist/${id}

建立一個函式,名稱為 addItem,我們傳入待辦事項的物件,之後藉由 fetch 發送 POST request,新增資料到後端。

    const addItem = item => {
        fetch('http://localhost:3000/todolist', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(item)
        })
        .then(res => res.json())
        .then(json => {
            todoList.push(json);
            render(todoList);
        })
    }

在資料成功返回後,我們就將待辦事項的物件加到 todoList 裡,並繪製畫面。


修改待辦事項清單

我們大概會有以下幾個步驟

  • 抓取需要的 DOM 物件(ul#todoList)
  • 監聽 ul#todoList 的 click 事件
  • 當 click 事件觸發時,判斷是不是點擊修改區塊
    • 如果不是,就不做任何事
    • 如果是,就發送 HTTP Request(PUT)
  • 當 HTTP Response 時,更新畫面

抓取需要的 DOM 物件(ul#todoList)

由於修改待辦事項是透過點擊待辦內容(ul#todoList)裡的項目 icon項目文字來做修改,所以我們新增 todoListDOM 來抓取 ul#todoList 的 DOM 之後再進一步做操作。

const todoListDOM = document.getElementById('todoList');

監聽 ul#todoList 的 click 事件

當使用者點擊待辦事項內清單的項目,就會觸發修改待辦事項的行為。

todoListDOM.addEventListener('click', event => {
	// 點擊後的處理
});

當 click 事件觸發時,判斷是不是點擊修改區塊

修改區塊包括項目 icon (.finish 跟 .unfinished) 及項目文字 (.desc)

todoListDOM.addEventListener('click', event => {
    const currentTarget = event.target;
    
    if (currentTarget && (currentTarget.matches('a.unfinished') || currentTarget.matches('a.finish') || currentTarget.matches('.desc'))) {
        // 點擊待辦事項內的項目icon及項目文字,執行修改待辦事項的方法
        toggleItem(parseInt(currentTarget.dataset.id, 10))
    }
});

toggleItem 為修改待辦事項的方法,會傳入當前修改的 id後透過 Array.prototype.find() 去找到當前選擇項目,再去切換待辦事項裡『已完成』和『未完成』的狀態,最後發出 HTTP Request(PUT)傳送修改內容。

    const toggleItem = id => {
        const currentSelectItem = todoList.find(item => item.id === id);
        // 切換『已完成』和『未完成』狀態
        currentSelectItem.isComplete = !currentSelectItem.isComplete;
        fetch(`http://localhost:3000/todolist/${id}`, {
            method: 'PUT',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(currentSelectItem)
        })
        .then(res => res.json())
        .then(json => {
            render(todoList);
        })
    }  

刪除待辦事項

我們大概會有以下幾個步驟

  • 抓取需要的 DOM 物件(ul#todoList)
  • 監聽 ul#todoList 的 click 事件
  • 當 click 事件觸發時,判斷是不是點擊 deleteButton
    • 如果不是,就不做任何事
    • 如果是,就發送 HTTP Request(DELETE)
  • 當 HTTP Response 時,更新畫面

抓取需要的 DOM 物件(ul#todoList)

因為刪除待辦事項的按鈕在待辦內容(ul#todoList)裡,所以新增 todoListDOM 來抓取 ul#todoList 的 DOM。

const todoListDOM = document.getElementById('todoList');

監聽 ul#todoList 的 click 事件

當使用者點擊待辦事項內的『刪除按鈕』,就會觸發刪除待辦事項的行為。

todoListDOM.addEventListener('click', event => {
	// 點擊後的處理
});

當 click 事件觸發時,判斷是不是點擊刪除按鈕

之前有判斷過修改區塊包括項目 icon (.finish 跟 .unfinished) 及項目文字 (.desc),這次再加上刪除按鈕(a.del)。

todoListDOM.addEventListener('click', event => {
    const currentTarget = event.target;
    if (currentTarget && (currentTarget.matches('a.unfinished') || currentTarget.matches('a.finish') || currentTarget.matches('.desc'))) {
		    // 點擊待辦事項內項目icon及項目文字,執行修改待辦事項的方法
        toggleItem(parseInt(currentTarget.dataset.id, 10))
    } else if (currentTarget && currentTarget.matches('a.del')) {
        // 點擊待辦事項內的刪除 icon,觸發刪除待辦事項的行為
        removeItem(parseInt(currentTarget.dataset.id, 10))
    }
});

removeItem 為刪除待辦事項的方法,會傳入當前修改的 id後,發出 HTTP Request(DELETE)。

const removeItem = id => {
    fetch(`http://localhost:3000/todolist/${id}`, {
        method: 'DELETE',
        headers: {
            'Content-Type': 'application/json'
        }
    })
    .then(res => res.json())
    .then(json => {
        todoList = todoList.filter(item => item.id !== id);
        render(todoList);
    })
}

最後再透過 render(todoList); 更新畫面(可參考前一篇文章)。

function render (todoList) {
    renderTodoList(todoList);
}

function renderTodoList (todoList) {
    const html = todoList.map((item, index) => `<li class="list">
            <a class="${item.isComplete ? 'finish' : 'unfinished'}" data-id=${item.id}></a>
            <p class="desc" data-id=${item.id}>
                ${item.desc}
            </p>
            <a class="del" data-id=${item.id}></a>
        </li>`).join('')
    todoListDOM.innerHTML = html;
}

本日小結

我們透過 Vanilla JS 去實作 To-Do List 的範例,逐步講解 - 新增/修改/刪除待辦事項所執行的功能並藉由 REST API 完成對應行為。


本人小小筆記,如有錯誤或需要改進的部分,歡迎給予回饋。
我將會用最快的速度修正,m(_ _)m。謝謝

上一篇
Day 19 - 30 天 Progressive Web App 學習筆記 - 實作 PWA To-Do List - 顯示待辦事項清單
下一篇
Day 21 - 30 天 Progressive Web App 學習筆記 - To-Do List 實作 PWA - Web App Manifest File
系列文
30 天 Progressive Web App 學習筆記30

尚未有邦友留言

立即登入留言