還記得第二篇的待辦清單嗎?只要重新整理網頁,所有項目就消失了。這一篇要用一個很簡單的功能解決這個問題:localStorage。它可以把資料存在使用者的瀏覽器裡,關掉網頁再打開,資料還在。
一、什麼是 localStorage?
localStorage 是瀏覽器內建的小型儲存空間,以「名稱(key)」與「值(value)」成對存放資料,不需要伺服器或資料庫。
- 關閉瀏覽器後資料依然存在。
- 每個網站各自獨立,彼此看不到對方的資料。
- 容量大約 5MB,適合存放設定、簡單清單等小資料。
- 只能存「字串」。
二、四個基本指令
在瀏覽器按 F12 打開 Console,直接輸入看看:
// 1. 存入資料
localStorage.setItem("username", "小明");
// 2. 讀取資料
console.log(localStorage.getItem("username")); // 小明
// 3. 刪除單筆資料
localStorage.removeItem("username");
// 4. 清空全部資料
localStorage.clear();
如果讀取一個不存在的名稱,會得到 null。
想親眼看到資料存在哪裡:按 F12,切換到「Application(應用程式)」分頁,左側找到 Local Storage,就能看到存起來的內容。
三、存放陣列與物件
localStorage 只能存字串,所以陣列和物件要先用 JSON.stringify() 轉成字串,讀取時再用 JSON.parse() 轉回來:
const fruits = ["蘋果", "香蕉", "橘子"];
// 存入:陣列 → 字串
localStorage.setItem("fruits", JSON.stringify(fruits));
// 讀取:字串 → 陣列
const saved = JSON.parse(localStorage.getItem("fruits"));
console.log(saved[0]); // 蘋果
如果忘記轉換,存進去的會變成 [object Object] 這種沒有用的字串,這是初學者最常犯的錯。
四、處理「第一次使用」的情況
第一次打開網頁時,localStorage 裡還沒有資料,getItem 會回傳 null。我們可以用上一篇學到的 ?? 設定預設值:
const todos = JSON.parse(localStorage.getItem("todos")) ?? [];
console.log(todos); // 第一次使用時是 []
五、綜合範例:會記住內容的待辦清單
把第二篇的待辦清單加上 localStorage。做法很單純:每次資料有變動就存檔,網頁載入時就讀檔。存成 todo-save.html 並用瀏覽器開啟,新增幾筆後重新整理看看:
<!DOCTYPE html>
<html lang="zh-Hant">
<head>
<meta charset="UTF-8">
<title>會記住的待辦清單</title>
<style>
.done { text-decoration: line-through; color: gray; }
li { cursor: pointer; margin: 6px 0; }
</style>
</head>
<body>
<h1>我的待辦清單</h1>
<form id="todoForm">
<input type="text" id="todoInput" placeholder="輸入待辦事項" required>
<button type="submit">新增</button>
</form>
<ul id="todoList"></ul>
<button id="clearBtn">清除全部</button>
<script>
const form = document.querySelector("#todoForm");
const input = document.querySelector("#todoInput");
const list = document.querySelector("#todoList");
const clearBtn = document.querySelector("#clearBtn");
// 1. 載入時讀取資料(第一次使用則為空陣列)
let todos = JSON.parse(localStorage.getItem("todos")) ?? [];
// 2. 存檔函式
function save() {
localStorage.setItem("todos", JSON.stringify(todos));
}
// 3. 把資料畫到畫面上
function render() {
list.innerHTML = "";
todos.forEach(function (todo, index) {
const li = document.createElement("li");
li.textContent = todo.text;
li.dataset.index = index;
if (todo.done) li.classList.add("done");
list.appendChild(li);
});
}
// 4. 新增項目
form.addEventListener("submit", function (e) {
e.preventDefault();
const text = input.value.trim();
if (text === "") return;
todos.push({ text: text, done: false });
save();
render();
input.value = "";
});
// 5. 點一下切換完成狀態
list.addEventListener("click", function (e) {
if (e.target.tagName === "LI") {
const i = e.target.dataset.index;
todos[i].done = !todos[i].done;
save();
render();
}
});
// 6. 連點兩下刪除
list.addEventListener("dblclick", function (e) {
if (e.target.tagName === "LI") {
todos.splice(e.target.dataset.index, 1);
save();
render();
}
});
// 7. 清除全部
clearBtn.addEventListener("click", function () {
todos = [];
save();
render();
});
// 網頁一載入就先畫出已存的資料
render();
</script>
</body>
</html>
程式的核心觀念只有一個:資料變了就 save(),畫面要更新就 render()。把「資料」與「畫面」分開處理,是之後學習各種前端框架的基礎。
六、注意事項
- 不要存敏感資料:localStorage 的內容任何人都能在開發者工具中看到,請不要存放密碼、身分證字號等機密資訊。
- 使用者可以自行清除:清除瀏覽器資料後,localStorage 就會消失,所以它不能取代真正的資料庫。
- 不同瀏覽器、不同裝置之間不會同步:在電腦存的資料,手機上是看不到的。
- 與 sessionStorage 的差異:用法完全相同,但 sessionStorage 在關閉分頁後就會清除。
七、練習題
- 製作一個輸入框,輸入暱稱後存起來,下次開啟網頁時顯示「歡迎回來,暱稱!」。
- 製作一個計數器按鈕,每按一次加 1,重新整理後數字不會歸零。
- 在「深色/淺色模式」按鈕中,記住使用者上次選擇的模式。
結語
localStorage 簡單又實用,只要記住 setItem、getItem,加上 JSON.stringify 與 JSON.parse 的轉換,就能讓你的小工具擁有「記憶」。有任何問題,歡迎在下方留言討論!
沒有留言:
張貼留言