昨天把新增筆記後的操作收尾,讓輸入框可以自動清空,並且把游標放回輸入框。
今天開始處理另一個核心功能:刪除筆記。
在畫面上放一個刪除按鈕不難,真正需要處理的是,當頁面上同時有很多則筆記時,程式要怎麼知道使用者想刪除的是哪一則?
總不能按下其中一個刪除按鈕,結果整個清單一起消失。
為了延續前幾天「一次只處理一件事」的方式,我把這次的任務限制在刪除功能:
請替每一則筆記加入刪除按鈕。使用者點擊後,只刪除對應的那一則資料,再重新顯示筆記清單。這次不要加入編輯功能。
這次要確認的不只是按鈕有沒有出現,還要實際測試刪除第一則、中間一則和最後一則筆記時,結果是否都正確。
假設目前有兩則內容完全相同的筆記:
[
{
id: 101,
content: "記得買牛奶"
},
{
id: 102,
content: "記得買牛奶"
}
]
如果程式只根據文字判斷,很可能無法分辨使用者到底想刪除哪一則。
所以前面建立筆記資料時加入的 id,現在終於派上用場。
即使兩則筆記的內容完全相同,只要 id 不同,程式就能把它們視為兩筆獨立資料。
產生筆記畫面時,每一則筆記都會建立自己的刪除按鈕。
const deleteButton = document.createElement("button");
deleteButton.textContent = "刪除";
deleteButton.addEventListener("click", () => {
deleteNote(note.id);
});
當使用者點擊按鈕時,程式會把目前這則筆記的 id 傳給 deleteNote()。
這樣每個刪除按鈕看起來雖然一樣,背後帶入的編號卻不同。
第一則筆記的按鈕可能傳入 101,第二則則傳入 102。程式因此能確定使用者真正選中的是哪一筆資料。
filter() 留下其他筆記取得目標 id 後,可以利用陣列的 filter() 移除指定資料:
function deleteNote(id) {
notes = notes.filter((note) => note.id !== id);
}
這段程式不是直接找到某一筆資料並把它拔掉,而是重新建立一個陣列。
它會逐一檢查每則筆記:
id 不等於目標編號的筆記,留下來id 等於目標編號的筆記,不放進新陣列最後得到的結果,就是少了指定筆記的新清單。
我以前看到 filter() 時,總覺得「篩選」和「刪除」是兩件不同的事。
放進這個功能後就比較容易理解:刪除指定資料,也可以換個方向思考成「只留下其他資料」。
const 和 let 的差別原本如果使用 const 宣告筆記陣列:
const notes = [];
就不能再將一個新的陣列指定給 notes:
notes = notes.filter((note) => note.id !== id);
因為 filter() 會回傳新的陣列,而 const 宣告的變數不能被重新指定。
如果採用這種刪除方式,筆記陣列就要改成:
let notes = [];
這不是因為陣列內容會改變,所以一定要使用 let。
真正的原因是,這裡會將 notes 重新指定成另一個陣列。
這個差別很小,但如果沒有檢查 Codex 修改的內容,我可能只會看到 const 突然變成 let,卻不知道它為什麼要改。
執行 filter() 後,陣列裡的資料已經改變,但畫面不會自己跟著更新。
因此,刪除完成後還要重新執行顯示筆記的函式:
function deleteNote(id) {
notes = notes.filter((note) => note.id !== id);
renderNotes();
}
如果只修改陣列,卻沒有再次呼叫 renderNotes(),使用者仍然會看到那則筆記留在畫面上。
這時就會出現一個很奇怪的狀態:畫面看起來沒有刪除成功,但程式裡其實已經找不到那筆資料。
所以每次資料發生變化後,都要記得同步更新畫面。
刪除和新增不太一樣。
新增錯了,之後還有機會修改;但如果誤觸刪除按鈕,目前又沒有復原功能,那則筆記就會直接消失。
第一版最簡單的作法,是先使用瀏覽器內建的確認視窗:
const confirmed = window.confirm("確定要刪除這則筆記嗎?");
if (!confirmed) {
return;
}
使用者按下取消時,函式會停止;只有按下確定,才會繼續刪除資料。
瀏覽器內建視窗的外觀不一定好看,但目前比立刻製作一個自訂對話框簡單,也可以先避免誤刪。
等主要功能完成後,再決定要不要換成符合 Idea Note 風格的確認視窗。
這次至少需要測試以下情況:
其中最重要的是相同內容的測試。
如果兩則「記得買牛奶」只消失了被點選的那一則,就表示程式真正依靠的是 id,而不是畫面上的文字。
今天完成的不只是一個刪除按鈕,而是讓每個按鈕都能找到自己對應的資料。
下一篇,我會開始處理編輯功能,讓使用者可以修改原本的筆記,而不是每次寫錯都只能刪掉重來。