昨天我們讓 AI Agent 幫忙建立了網站收藏管理器的第一版 UI,畫面上已經有輸入框、分類選單、搜尋欄位,以及顯示收藏網站的卡片。
看起來似乎已經有模有樣了,但其實還有一個很大的問題:按鈕只是裝飾品,根本不能用。
所以今天的目標很簡單,就是讓昨天做好的畫面真正動起來。
這次不需要重新建立專案,而是直接開啟昨天的 BookmarkManager,請 Agent 在原本的基礎上加入 JavaScript 功能。
這次的 Prompt 可以寫得更明確一點:
請根據目前 BookmarkManager 專案的 HTML 與 CSS,使用原生 JavaScript 實作以下功能:
- 使用者輸入網站名稱、網址並選擇分類後,可以按下按鈕新增收藏。
- 新增的網站要顯示在收藏卡片區域,包含名稱、網址與分類。
- 每張收藏卡片都要有刪除按鈕,可以刪除指定收藏。
- 搜尋欄位可以即時根據網站名稱篩選收藏。
- 如果網站名稱或網址沒有填寫,要顯示提示訊息。
請沿用原本的 UI,不要重新設計畫面,也不要使用任何第三方套件。
今天先讓功能在網頁執行期間正常運作,不要加入 LocalStorage 或其他資料儲存方式。完成後請說明修改了哪些檔案。
這次特別強調不要改動 UI,也不要加入資料保存功能。
畢竟我們是要讓 AI 接續昨天的進度,而不是每次下 Prompt 都重新做一個網站。
首先,新增收藏需要一個地方存放資料。
最簡單的方式就是使用 JavaScript 陣列:
let bookmarks = [];
function addBookmark() {
const name = document.getElementById("siteName").value.trim();
const url = document.getElementById("siteUrl").value.trim();
const category = document.getElementById("category").value;
if (!name || !url) {
alert("請填寫網站名稱與網址");
return;
}
let parsedUrl;
try {
parsedUrl = new URL(url);
if (!["http:", "https:"].includes(parsedUrl.protocol)) {
throw new Error("不支援的網址格式");
}
} catch {
alert("請輸入有效的 http 或 https 網址");
return;
}
bookmarks.push({
id: crypto.randomUUID(),
name,
url: parsedUrl.href,
category
});
renderBookmarks();
}
這段程式會先取得輸入框的資料,確認名稱與網址沒有留空,再把新的收藏加入 bookmarks 陣列。
其中 renderBookmarks() 是等等用來更新畫面的函式。
至於完整的表單事件綁定、清空輸入框等細節,就讓 Agent 一起處理。
新增功能完成後,接下來就是刪除。
這部分其實不需要什麼複雜的演算法,只要找到指定的收藏,再從陣列中移除即可。
function deleteBookmark(id) {
bookmarks = bookmarks.filter(
bookmark => bookmark.id !== id
);
renderBookmarks();
}
這裡使用 filter(),保留所有 ID 不等於指定 ID 的收藏,最後再更新畫面。
不過要注意,刪除的是指定收藏,不是把整個列表清空。
這也是為什麼前面新增資料時,會替每筆收藏建立獨立的 ID。
最後則是搜尋功能。
這次不需要額外的搜尋按鈕,只要使用者在搜尋框輸入文字,畫面就立即更新。
const searchInput = document.getElementById("searchInput");
searchInput.addEventListener("input", () => {
renderBookmarks();
});
而在 renderBookmarks() 裡,可以根據搜尋文字篩選資料:
function renderBookmarks() {
const keyword = searchInput.value.trim().toLowerCase();
const filtered = bookmarks.filter(bookmark =>
bookmark.name.toLowerCase().includes(keyword)
);
// 清空原本的收藏卡片
// 根據 filtered 建立新的卡片
// 為刪除按鈕綁定 deleteBookmark()
// 使用 textContent 顯示使用者輸入的文字
// 使用 DOM API 建立安全的連結與按鈕
...
}
這裡省略了建立 HTML 元素的細節,完整的 renderBookmarks() 可以讓 Agent 依照昨天的卡片樣式產生。
實作時記得讓 Agent 使用 textContent 顯示收藏名稱,不要直接把使用者輸入的內容拼進 innerHTML,避免產生不必要的安全問題。
程式修改完成後,就可以開啟 index.html 進行測試。
我會先新增幾筆測試資料:
| 網站名稱 | 網址 | 分類 |
|---|---|---|
| GitHub | https://github.com | 學習 |
| YouTube | https://youtube.com | 娛樂 |
| MDN Web Docs | https://developer.mozilla.org | 學習 |
接著試試在搜尋框輸入 Git,看看畫面是不是只剩 GitHub,再按下刪除按鈕,確認它真的從列表中消失。
如果三個功能都能正常使用,今天的目標就算完成了。
不過這時候還有一個很明顯的問題。
只要重新整理網頁,剛剛新增的收藏就會全部消失。
因為目前所有資料都只是存在 JavaScript 陣列裡,網頁重新載入後,陣列自然也會重新初始化。
但這個問題先不用急著處理,因為它正好就是明天的主題。
Day 26,我們就來讓 AI 幫忙加入 LocalStorage,讓收藏資料在重新整理網頁之後也能保留下來。