iT邦幫忙

2026 iThome 鐵人賽

DAY 29
0
自我挑戰組

30 天,挑戰我的 Web 前端力系列 第 29 篇

JavaScript:寫錯了不能刪??哈納記事本終於有刪除鍵了!

  • 分享至 

  • xImage
  •  

昨天成功把 LocalStorage 接進哈納小小記事本。

現在就算按:

F5

記事也不會集體失憶了。

本來覺得:

很好,這東西終於有一點記事本的樣子了。

結果用一用馬上發現新的問題。

我手滑輸入:

記得買哈納的罐罐罐罐罐罐

……

沒事。

刪掉就好。

然後我看了一下畫面。

蛤?沒有刪除鍵???

所以目前這個記事本的規則是:

寫出去的話,就像潑出去的水。

不是欸。

我只是寫記事本,不是在立誓欸 ==

所以 Day 29 決定把最後一個重要功能補起來:

刪除記事!


先幫每篇記事加一顆刪除按鈕

昨天的 renderNotes() 是:

function renderNotes() {
  noteList.innerHTML = "";

  notes.forEach(function (note) {
    const li = document.createElement("li");

    li.textContent = note.text;

    noteList.appendChild(li);
  });
}

今天要多一顆按鈕。

改成:

function renderNotes() {
  noteList.innerHTML = "";

  notes.forEach(function (note) {
    const li = document.createElement("li");

    const text = document.createElement("span");
    const deleteBtn = document.createElement("button");

    text.textContent = note.text;

    deleteBtn.textContent = "刪除";
    deleteBtn.dataset.id = note.id;

    li.appendChild(text);
    li.appendChild(deleteBtn);

    noteList.appendChild(li);
  });
}

現在每一筆記事旁邊都會多一顆:

刪除

終於。

寫錯字不用跟它相處一輩子了 XD


dataset.id 又是什麼?

這裡多了一個:

deleteBtn.dataset.id = note.id;

因為每一篇記事原本都有自己的:

id

例如:

{
  id: 1750000000000,
  text: "記得買哈納的罐罐"
}

所以我把這個 id 放到按鈕身上。

產生出來的 HTML 概念上會像:

<button data-id="1750000000000">
  刪除
</button>

之後按下刪除,

就可以知道:

你到底想刪哪一篇。

不然如果畫面上有十篇記事,

每一顆都叫「刪除」,

JavaScript 大概也會問:

好啊,所以你到底要刪誰???


Day 20 的 Event Delegation 回來上班!

看到這麼多刪除按鈕,

原本第一個想法可能是:

每顆按鈕都加 addEventListener()

但等等。

這個畫面好熟悉。

Day 20 才學過:

Event Delegation(事件代理)

所以這次直接監聽外面的:

noteList
noteList.addEventListener("click", function (event) {
  if (event.target.tagName !== "BUTTON") {
    return;
  }

  console.log(event.target.dataset.id);
});

這樣不管點的是哪一篇的刪除按鈕,

都可以透過:

event.target

知道真正被點到的是誰。

以前學的東西終於真的出現在作品裡。

Day 20 的我沒有白學 QQ


找到 ID,真的把它刪掉

接下來就要從 notes 裡把那筆資料移除。

這時候又輪到之前學過的:

filter()

上班。

notes = notes.filter(function (note) {
  return note.id !== id;
});

意思就是:

把不是這個 id 的記事全部留下。

那個被點到的記事?

不好意思。

你被篩掉了 XD

完整一點:

noteList.addEventListener("click", function (event) {
  if (event.target.tagName !== "BUTTON") {
    return;
  }

  const id = Number(event.target.dataset.id);

  notes = notes.filter(function (note) {
    return note.id !== id;
  });

  saveNotes();
  renderNotes();
});

流程變成:

點刪除
↓
取得這篇記事的 ID
↓
用 filter() 移除資料
↓
重新存進 LocalStorage
↓
重新 render

為什麼刪除後還要 saveNotes()?

如果只有:

notes = notes.filter(...)

再:

renderNotes();

畫面上的確會消失。

看起來超成功。

然後按一下 F5。

……

它又回來了。

哈囉???

你是幽靈記事是不是 ==

原因就是:

畫面跟 Array 雖然刪掉了,

但 LocalStorage 裡的舊資料還在。

所以刪除之後一定還要:

saveNotes();

把最新的 Array 再存一次。

這樣才是真的刪掉。

不是單純:

眼不見為淨。


順便把版面整理一下

既然現在一篇記事裡有:

記事內容 + 刪除按鈕

CSS 也稍微補一下:

#noteList li {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;

  margin-bottom: 10px;
  padding: 12px 15px;

  background-color: #fff0f3;
  border-radius: 8px;
}

#noteList li span {
  flex: 1;
  word-break: break-word;
}

#noteList li button {
  border: none;
  padding: 8px 12px;
  border-radius: 6px;

  background-color: #ff6b81;
  color: white;

  cursor: pointer;
}

#noteList li button:hover {
  opacity: 0.8;
}

前面學過的 Flexbox:

display: flex;

又來了。

突然覺得這 29 天學的東西,

真的很像一群同事。

平常各上各的班,

做作品的時候突然:

全部進會議室集合。


今天完整的刪除流程

現在記事本的功能已經變成:

輸入記事
↓
按新增
↓
加入 Array
↓
存入 LocalStorage
↓
顯示到網頁

以及:

按刪除
↓
取得 ID
↓
filter() 移除資料
↓
更新 LocalStorage
↓
重新顯示

原本單獨學的:

filter()
event.target
LocalStorage

現在居然全部接在一起了。

這種感覺滿奇妙的。

以前是:

這個語法到底拿來幹嘛?

現在是:

喔,原來你在這裡等我。


今天的小心得

到 Day 29,

哈納小小記事本現在已經可以:

  • 新增記事
  • 顯示記事
  • 重新整理後保留資料
  • 刪除不要的記事
  • 手機版也不至於直接爆掉

從一開始只有:

<input>
<button>

慢慢加到現在,

終於開始真的像一個可以使用的小作品。

而且今天最有感的反而不是多了一顆「刪除」按鈕。

而是發現前面學過的:

Array、filter()、DOM、Event Delegation、LocalStorage、Flexbox……

真的開始自己串起來了。

哈納也從一開始只是:

console.log("哈納");

一路進化成現在直接擁有自己的記事本。

牠本人應該完全沒有同意這件事 XD

https://ithelp.ithome.com.tw/upload/images/20260929/20178938mOIPtDvYcy.png

刪除後:

https://ithelp.ithome.com.tw/upload/images/20260929/201789383RADDbUZag.png
剩最後一天。

這次真的差不多要來看看,

這 30 天到底被我折騰出了什麼東西。

Day 29,完成!


上一篇
JavaScript:F5 一按全失憶?LocalStorage 給我記住!!!
系列文
30 天,挑戰我的 Web 前端力 共 29 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言