JavaScript使用LocalStorage實現(xiàn)本地待辦事項(To-Do)列表
引言
在現(xiàn)代 Web 開發(fā)中,前端開發(fā)者常常需要在瀏覽器中持久化存儲一些用戶數(shù)據(jù)。比如用戶的偏好設(shè)置、表單草稿、或者像本文要實現(xiàn)的——一個簡單的待辦事項(To-Do List)應(yīng)用。HTML5 提供了一個非常實用的 API:localStorage,它允許我們在用戶的瀏覽器中以鍵值對的形式永久保存數(shù)據(jù)。
本文將通過一個完整的示例,帶你了解如何使用 localStorage 實現(xiàn)一個可持久化存儲的 To-Do 列表,并結(jié)合 JavaScript 的函數(shù)式編程思想和事件委托機(jī)制,寫出結(jié)構(gòu)清晰、易于維護(hù)的代碼。
什么是 localStorage?
localStorage 是 Web Storage API 的一部分,用于在瀏覽器中長期存儲數(shù)據(jù)。它的特點包括:
- 持久性:除非用戶手動清除,否則數(shù)據(jù)不會過期。
- 鍵值對存儲:只能存儲字符串類型的數(shù)據(jù)(key 和 value 都是字符串)。
- 同源策略:只有同協(xié)議、同域名、同端口的頁面才能共享同一個
localStorage。
由于 localStorage 只能存字符串,因此我們通常會配合 JSON.stringify() 和 JSON.parse() 來存儲和讀取對象或數(shù)組。
項目結(jié)構(gòu)概覽
我們的目標(biāo)是實現(xiàn)一個簡單的“Tapas”(小食)清單,用戶可以:
- 添加新的 Tapas 項;
- 勾選已完成的項;
- 頁面刷新后數(shù)據(jù)依然保留。
HTML 結(jié)構(gòu)如下:
<div class="wrapper">
<h2>LOCAL TAPAS</h2>
<ul class="plates">
<li>Loading Tapas...</li>
</ul>
<form class="add-items">
<input type="text" placeholder="Item Name" required name="item">
<input type="submit" value="+ Add Item">
</form>
</div>
核心邏輯集中在 <script> 標(biāo)簽中,下面我們逐步拆解。
初始化數(shù)據(jù)與渲染列表
首先,我們從 localStorage 中讀取已有的待辦事項:
const items = JSON.parse(localStorage.getItem('todos')) || [];
如果 localStorage 中沒有 'todos' 這個 key,就返回一個空數(shù)組作為默認(rèn)值。
接著,我們封裝一個 populateList 函數(shù),用于將數(shù)據(jù)渲染到頁面上:
function populateList(plates = [], platesList) {
platesList.innerHTML = plates.map((plate, i) => {
return `
<li>
<input type="checkbox" data-index=${i} id="item${i}" ${plate.done ? 'checked' : ''} />
<label for="item${i}">${plate.text}</label>
</li>
`;
}).join('');
}
這個函數(shù)接收兩個參數(shù):
plates:待辦事項數(shù)組;platesList:要渲染到的 DOM 元素(即<ul class="plates">)。
通過 map 方法生成每個列表項的 HTML 字符串,并用 join('') 拼接成完整內(nèi)容,最后賦值給 innerHTML。這種方式避免了頻繁操作 DOM,性能更優(yōu)。
調(diào)用一次即可完成初始渲染:
populateList(items, itemsList);
添加新事項
當(dāng)用戶在表單中輸入內(nèi)容并點擊“+ Add Item”時,會觸發(fā) submit 事件。我們通過事件監(jiān)聽器處理:
addItems.addEventListener('submit', addItem);
addItem 函數(shù)的核心邏輯如下:
function addItem(e) {
e.preventDefault(); // 阻止表單默認(rèn)提交(頁面跳轉(zhuǎn))
const text = this.querySelector('[name=item]').value.trim();
//通過屬性選擇器 拿到表單中name為item的input中的值 并去除左右空格 這里其實也運(yùn)用到包裝類的概念
//因為拿到的value是字符串 簡單數(shù)據(jù)類型 但是可以調(diào)用方法.trim()
const item = {
text,
done: false
//通過done來控制勾選框的選中 一開始設(shè)置為false
};
items.push(item);//把輸入的item添加到items
localStorage.setItem('todos', JSON.stringify(items)); // 持久化存儲
populateList(items, itemsList); // 重新渲染
this.reset(); // 清空表單內(nèi)容 優(yōu)化用戶體驗
}
這里有幾個關(guān)鍵點:
- 使用
e.preventDefault()防止頁面刷新; - 通過
this(指向表單元素)獲取輸入框的值; - 構(gòu)造新對象
{ text, done: false }并加入數(shù)組; - 調(diào)用
localStorage.setItem()將整個數(shù)組轉(zhuǎn)為字符串后保存; - 重新渲染列表并清空表單。
勾選/取消勾選事項(事件委托)
如果為每個復(fù)選框單獨綁定事件,效率低下且難以維護(hù)。因此我們采用事件委托:將點擊事件綁定在父容器 <ul class="plates"> 上,通過判斷點擊目標(biāo)是否為 input 來決定是否處理。
itemsList.addEventListener('click', toggleDone);
function toggleDone(e) {
const el = e.target;
//指定 當(dāng)點擊的為input時 才進(jìn)行下面操作
if (el === 'INPUT') {
const index = el.dataset.index;
items[index].done = !items[index].done;
//通過done來控制勾選 點擊取反
localStorage.setItem('todos', JSON.stringify(items));
//點擊后修改了item中的done值 再次進(jìn)行本地存儲
populateList(items, itemsList);//再次渲染
}
}
每次切換狀態(tài)后,我們同樣更新 localStorage 并重新渲染整個列表,確保視圖與數(shù)據(jù)一致。
為什么使用函數(shù)式封裝?
文中提到:“拒絕流程式代碼,超過10行就封裝函數(shù)”。這其實是一種良好的編程習(xí)慣:
- 提高可讀性:
populateList、addItem等函數(shù)名清晰表達(dá)了意圖; - 便于復(fù)用:渲染邏輯被抽離,可在多處調(diào)用;
- 降低耦合:數(shù)據(jù)操作與 DOM 操作分離,邏輯更清晰;
- 易于測試與調(diào)試:每個函數(shù)職責(zé)單一。
此外,默認(rèn)參數(shù)(如 plates = [])和解構(gòu)賦值(如 { text, done })也體現(xiàn)了 ES6 的簡潔語法優(yōu)勢。
總結(jié)
通過這個小小的“Local Tapas”項目,我們不僅實現(xiàn)了基本的增刪改查(CRUD)功能,更重要的是掌握了以下核心知識點:
localStorage的基本用法:存儲字符串、配合JSON處理復(fù)雜數(shù)據(jù);- 事件委托:高效處理動態(tài)生成元素的交互;
- 函數(shù)式編程思想:封裝細(xì)節(jié)、關(guān)注輸入輸出;
- DOM 操作優(yōu)化:批量更新而非逐個操作。
雖然這個應(yīng)用很簡單,但它展示了現(xiàn)代前端開發(fā)中“數(shù)據(jù)驅(qū)動視圖”的典型模式:數(shù)據(jù)變化 → 更新存儲 → 重新渲染。這種模式也是 React、Vue 等框架的思想基礎(chǔ)。
你可以在此基礎(chǔ)上繼續(xù)擴(kuò)展,比如:
- 添加刪除按鈕;
- 支持編輯事項;
- 按完成狀態(tài)過濾;
- 加入動畫效果等。
但無論如何,記?。?strong>好的代碼始于清晰的結(jié)構(gòu)和合理的抽象。而 localStorage,正是你構(gòu)建離線優(yōu)先(Offline-First)應(yīng)用的第一步。
以上就是JavaScript使用LocalStorage實現(xiàn)本地待辦事項(To-Do)列表的詳細(xì)內(nèi)容,更多關(guān)于JS LocalStorage本地待辦事項列表的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
JavaScript從數(shù)組中刪除某個特定元素的多種方法
數(shù)組操作是編程中非常常見的一項技能,尤其是在處理數(shù)據(jù)、管理列表和更新界面時,刪除數(shù)組中的特定元素是我們常見的操作之一,本文將介紹如何從數(shù)組中刪除某個特定的元素,并結(jié)合實際項目代碼示例進(jìn)行講解,需要的朋友可以參考下2025-06-06
JavaScript 中定義函數(shù)用 var foo = function () {} 和 function foo()區(qū)
這篇文章主要介紹了JavaScript 中定義函數(shù)用 var foo = function () {} 和 function foo()區(qū)別介紹,需要的朋友可以參考下2018-03-03
javascript中的replace函數(shù)(帶注釋demo)
在js中有兩個replace函數(shù) 一個是location.replace(url) 跳轉(zhuǎn)到一個新的url.一個string.replace("xx","yy") 替換字符串 返回一個新的字符串,該方法并不改變字符串本身。下面通過本文給大家介紹javascript中的replace函數(shù)2018-01-01
js中confirm實現(xiàn)執(zhí)行操作前彈出確認(rèn)框的方法
這篇文章主要介紹了js中confirm實現(xiàn)執(zhí)行操作前彈出確認(rèn)框的方法,是執(zhí)行刪除等操作時常用的功能,非常具有實用價值,需要的朋友可以參考下2014-11-11

