React如何使用localStorage及實(shí)現(xiàn)刪除筆記操作過程
1. 初始化notes
以下這段代碼完成了這些操作:
- 調(diào)用
localStorage.getItem("notes")
從瀏覽器的本地存儲(chǔ)中獲取名為 “notes” 的數(shù)據(jù)。 - 使用
JSON.parse
將獲取到的字符串解析成數(shù)組。 - 如果本地存儲(chǔ)中沒有 “notes” 數(shù)據(jù)(返回值為 null),則默認(rèn)將 notes 設(shè)置為空數(shù)組 []。
const [notes, setNotes] = React.useState( JSON.parse(localStorage.getItem("notes")) || [] )
useState鉤子
useState 是 React 的一個(gè)鉤子,用于在函數(shù)組件中引入狀態(tài)。
它返回一個(gè)數(shù)組,有兩個(gè)元素:
- 當(dāng)前狀態(tài)值(這里是 notes)。
- 更新狀態(tài)的函數(shù)(這里是 setNotes)。
localStorage
localStorage
是瀏覽器提供的 API,用于在本地存儲(chǔ)鍵值對(duì)數(shù)據(jù)。localStorage.getItem("notes")
從localStorage
中獲取鍵為 “notes
” 的數(shù)據(jù),返回的結(jié)果是一個(gè)字符串。
JSON.parse
localStorage
中存儲(chǔ)的所有數(shù)據(jù)都是字符串。JSON.parse
將字符串解析為 JavaScript 對(duì)象。
如果存儲(chǔ)的數(shù)據(jù)是一個(gè) JSON 字符串,例如:“[1, 2, 3]”,調(diào)用 JSON.parse
后會(huì)得到 [1, 2, 3]。
|| 運(yùn)算符
- || 是邏輯或運(yùn)算符,用來提供一個(gè)默認(rèn)值。
- 如果
localStorage.getItem("notes")
返回 null(即沒有找到 “notes” 鍵),JSON.parse(localStorage.getItem("notes"))
的結(jié)果會(huì)是 null。 - 在這種情況下,表達(dá)式的右側(cè)([])會(huì)被返回,表示 notes 的初始值是一個(gè)空數(shù)組。
2. 每次notes發(fā)生改變時(shí),將notes保存到localStorage
React.useEffect(() => { localStorage.setItem("notes", JSON.stringify(notes)) }, [notes])
useEffect
是 React 的一個(gè)鉤子,用于在函數(shù)組件中處理副作用。
- 副作用通常指與組件渲染邏輯無關(guān)的行為,例如:數(shù)據(jù)獲取、訂閱、手動(dòng) DOM 操作、或者日志記錄等。
它的語法如下:
React.useEffect(effectFunction, dependencies);
effectFunction
是一個(gè)函數(shù),在特定條件下運(yùn)行。dependencies
是一個(gè)數(shù)組,控制 effectFunction
的運(yùn)行時(shí)機(jī)。
localStorage.setItem
是瀏覽器提供的 API,用于向 localStorage
中存儲(chǔ)鍵值對(duì)。
它接受兩個(gè)參數(shù):
- 鍵:存儲(chǔ)數(shù)據(jù)的名稱(這里是 “notes”)。
- 值:存儲(chǔ)的具體數(shù)據(jù),必須是字符串。
JSON.stringify(notes)
:
- 將 notes 轉(zhuǎn)換為 JSON 格式的字符串,因?yàn)?
localStorage
只能存儲(chǔ)字符串?dāng)?shù)據(jù)。
當(dāng)組件渲染后并且 notes 發(fā)生變化時(shí):
- useEffect 會(huì)被觸發(fā)。
- localStorage.setItem(“notes”, JSON.stringify(notes)) 將最新的 notes 數(shù)組保存到本地存儲(chǔ)中。
如果 notes 沒有變化:
- 即使組件重新渲染,useEffect 不會(huì)運(yùn)行,因?yàn)?notes 的值沒有改變。
3. 什么是 Lazy State Initialization?
通常情況下,useState 的初始值是直接計(jì)算出來的:
const [state, setState] = React.useState(computeInitialState());
- 這里
computeInitialState()
會(huì)在組件每次渲染時(shí)立即執(zhí)行,即使結(jié)果只需要在初次渲染時(shí)使用。 - 如果
computeInitialState
是一個(gè)復(fù)雜的計(jì)算函數(shù),就會(huì)浪費(fèi)性能。
為了解決這個(gè)問題,React 提供了一種惰性初始化的方法:通過向 useState 傳遞一個(gè)函數(shù),而不是直接傳遞計(jì)算結(jié)果。這種函數(shù)只會(huì)在組件第一次渲染時(shí)執(zhí)行,之后不會(huì)再次調(diào)用。
惰性初始化
const [state, setState] = React.useState(() => computeInitialState());
- 當(dāng)傳遞一個(gè)函數(shù)給 useState 時(shí),React 只會(huì)在組件初次渲染時(shí)調(diào)用這個(gè)函數(shù)來計(jì)算初始狀態(tài)。
- 后續(xù)的狀態(tài)更新不再調(diào)用此函數(shù)。
4. 在React中實(shí)現(xiàn)刪除筆記的操作
<button className="delete-btn" onClick={(event) => props.deleteNote(event, note.id)} > <i className="gg-trash trash-icon"></i> </button>
<button>
元素
- HTML 的按鈕標(biāo)簽,用于定義一個(gè)可點(diǎn)擊的交互元素。
- 在 React 中, 可以綁定事件和自定義屬性,并觸發(fā)相關(guān)的事件處理程序。
回調(diào)函數(shù)中的 (event) => props.deleteNote(event, note.id)
是一個(gè)箭頭函數(shù),執(zhí)行時(shí)調(diào)用 props.deleteNote
方法,并將兩個(gè)參數(shù)傳遞給它:
event
:原生的點(diǎn)擊事件對(duì)象,提供有關(guān)點(diǎn)擊的信息(如目標(biāo)元素、鼠標(biāo)位置等)。note.id
:當(dāng)前筆記的唯一標(biāo)識(shí)符,用于指定要?jiǎng)h除的具體筆記。
<i>
是 HTML 的行內(nèi)元素,通常用作圖標(biāo)的占位符。
function deleteNote(event, noteId){ event.stopPropagation() setNotes(oldNotes => oldNotes.filter(note => note.id !== noteId)) }
event.stopPropagation()
作用:
- 阻止事件從當(dāng)前元素傳播到父元素或其他祖先元素(即阻止事件冒泡)。
- 防止刪除按鈕的點(diǎn)擊事件觸發(fā)父組件的其他事件處理邏輯(如整個(gè)筆記項(xiàng)的點(diǎn)擊事件)。
場景舉例:
假設(shè)筆記項(xiàng)的外層組件有一個(gè)點(diǎn)擊事件綁定:
<div onClick={() => console.log("Note clicked!")}> <button onClick={(event) => deleteNote(event, noteId)}>Delete</button> </div>
如果沒有 event.stopPropagation()
:
- 點(diǎn)擊刪除按鈕時(shí),既會(huì)觸發(fā)
deleteNote
,又會(huì)觸發(fā)外層div
的onClick
。
有了 event.stopPropagation()
:
- 點(diǎn)擊刪除按鈕時(shí),只會(huì)觸發(fā)
deleteNote
。
箭頭函數(shù) oldNotes => oldNotes.filter(...)
setNotes
接收一個(gè)更新函數(shù),該函數(shù)的參數(shù)是當(dāng)前的狀態(tài)值 oldNotes
。
filter 方法:
- 返回一個(gè)新數(shù)組,其中包含滿足條件的所有元素。
- 條件:保留 id 不等于 noteId 的筆記,即刪除 noteId 對(duì)應(yīng)的筆記。
完整邏輯
通過 filter 遍歷 oldNotes 數(shù)組:
- 如果 note.id !== noteId,該筆記被保留。
- 如果 note.id === noteId,該筆記被過濾掉。
返回的新數(shù)組賦值給 notes,并觸發(fā)組件重新渲染。
5. 刪除按鈕的CSS實(shí)現(xiàn)
.delete-btn { display: none; background: none; border: none; }
作用
- 定義刪除按鈕的初始樣式,默認(rèn)情況下按鈕是隱藏的。
屬性解釋
- display: none;:
隱藏元素,按鈕不占據(jù)布局空間,不可見。
- background: none;:
移除按鈕的默認(rèn)背景樣式。
- border: none;:
移除按鈕的默認(rèn)邊框。
.title:hover > .delete-btn { display: block; }
作用
- 當(dāng)用戶將鼠標(biāo)懸停在 .title 元素上時(shí),其子元素 .delete-btn 顯示出來。
屬性解釋display: block;
:
讓 .delete-btn 可見,并以塊級(jí)元素形式顯示。
> .delete-btn
:
- 表示只選擇直接子元素 .delete-btn,避免影響其他嵌套更深的 .delete-btn。
實(shí)現(xiàn)邏輯
通過偽類 :hover
,動(dòng)態(tài)切換按鈕的顯示狀態(tài),提供更好的用戶交互體驗(yàn)。
.trash-icon { cursor: pointer; }
作用
- 定義垃圾桶圖標(biāo)的樣式,使其在用戶鼠標(biāo)懸停時(shí)具有點(diǎn)擊效果。
屬性解釋cursor: pointer;
:
鼠標(biāo)懸停時(shí)顯示手型指針,表示該元素可點(diǎn)擊。
.gg-trash { box-sizing: border-box; position: relative; display: block; transform: scale(var(--ggs,1)); width: 10px; height: 12px; border: 2px solid transparent; box-shadow: 0 0 0 2px, inset -2px 0 0, inset 2px 0 0; border-bottom-left-radius: 1px; border-bottom-right-radius: 1px; margin-top: 4px; }
作用
- 定義垃圾桶圖標(biāo)的外觀,包括大小、形狀和整體樣式。
屬性解釋box-sizing: border-box;
:
- 控制元素的寬高計(jì)算方式,包含內(nèi)邊距和邊框。
position: relative;
:
- 定義元素為相對(duì)定位,用于配合子元素的絕對(duì)定位。
transform: scale(var(--ggs,1));
:
- 使用 CSS 變量 --ggs 控制縮放比例,默認(rèn)為 1。
width: 10px; height: 12px;
:
- 定義垃圾桶的寬度和高度。
border: 2px solid transparent;
:
設(shè)置透明的邊框。
box-shadow
:
為垃圾桶形狀添加外邊框和內(nèi)部邊框:
- 0 0 0 2px:外部邊框,2px 寬。
- inset -2px 0 0 和 inset 2px 0 0:內(nèi)部分隔線。
border-bottom-left-radius
和 border-bottom-right-radius
:
- 為垃圾桶底部的兩個(gè)角添加圓角。
margin-top: 4px;
:
在頂部增加間距。
.gg-trash::after { background: currentColor; border-radius: 3px; width: 16px; height: 2px; top: -4px; left: -5px; }
作用
- 添加垃圾桶的橫梁部分(通常表示垃圾桶的蓋子)。
屬性解釋background: currentColor;
:
使用當(dāng)前文本顏色作為背景顏色。
border-radius: 3px;
:
添加圓角,使蓋子邊緣更平滑。
width: 16px; height: 2px;
:
定義橫梁的大小。
top: -4px; left: -5px;
:
使用絕對(duì)定位將橫梁放置在垃圾桶頂部的位置。
.gg-trash::before { width: 10px; height: 4px; border: 2px solid; border-bottom: transparent; border-top-left-radius: 2px; border-top-right-radius: 2px; top: -7px; left: -2px; }
作用
- 添加垃圾桶的蓋子部分(彎曲的頂部結(jié)構(gòu))。
屬性解釋
width: 10px; height: 4px;:
- 定義蓋子的寬度和高度。
border: 2px solid;:
設(shè)置蓋子的邊框。
border-bottom: transparent;:
移除蓋子底部的邊框,使其開口朝下。
border-top-left-radius 和 border-top-right-radius:
設(shè)置蓋子頂部的兩個(gè)角為圓角。
top: -7px; left: -2px;:
使用絕對(duì)定位將蓋子放置在垃圾桶頂部。
總結(jié):垃圾桶圖標(biāo)的整體實(shí)現(xiàn)
- .gg-trash 是垃圾桶的主體,包括邊框、陰影等基礎(chǔ)結(jié)構(gòu)。
- ::after 添加橫梁(垃圾桶蓋的下部分)。
- ::before 添加蓋子頂部的彎曲結(jié)構(gòu)。
結(jié)合這些樣式,實(shí)現(xiàn)了一個(gè)完整的垃圾桶圖標(biāo)。
交互效果總結(jié)
- .delete-btn 默認(rèn)隱藏,用戶鼠標(biāo)懸停在 .title 上時(shí)顯示。
- 鼠標(biāo)懸停時(shí),垃圾桶圖標(biāo)變?yōu)榭牲c(diǎn)擊狀態(tài),通過樣式 cursor: pointer 提供視覺提示。
6. 查找當(dāng)前筆記id
const [currentNoteId, setCurrentNoteId] = React.useState( (notes[0]?.id) || "" ) const currentNote = notes.find(note => note.id === currentNoteId) || notes[0]
React.useState
:
定義一個(gè)狀態(tài)變量 currentNoteId
和其對(duì)應(yīng)的更新函數(shù) setCurrentNoteId
。
notes[0]?.id
:
- 通過可選鏈操作符 (?.),嘗試訪問數(shù)組
notes
中第一項(xiàng)的 id。 - 如果 notes 數(shù)組為空或者
notes[0]
為undefined
,notes[0]?.id
返回undefined
而不會(huì)報(bào)錯(cuò)。
|| ""
:
如果 notes[0]?.id
為 undefined
,currentNoteId
的初始值設(shè)置為空字符串 ""
。
效果
如果 notes 數(shù)組非空,currentNoteId
的初始值是第一項(xiàng)筆記的 id。如果 notes 數(shù)組為空,currentNoteId
的初始值是 “”。
notes.find(note => note.id === currentNoteId)
:
- 使用
Array.prototype.find()
方法在 notes 數(shù)組中查找 id 等于currentNoteId
的筆記。 find
方法返回第一個(gè)滿足條件的元素。如果沒有找到匹配的元素,返回undefined
。
|| notes[0]
:
如果沒有找到匹配的筆記(即 find
返回 undefined
),使用 ||
提供默認(rèn)值,返回 notes[0]
(數(shù)組的第一項(xiàng))。
到此這篇關(guān)于React自學(xué):如何使用localStorage,以及如何實(shí)現(xiàn)刪除筆記操作的文章就介紹到這了,更多相關(guān)React localStorage刪除筆記內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
React實(shí)現(xiàn)點(diǎn)擊刪除列表中對(duì)應(yīng)項(xiàng)
本文主要介紹了React 點(diǎn)擊刪除列表中對(duì)應(yīng)項(xiàng)的方法。具有一定的參考價(jià)值,下面跟著小編一起來看下吧2017-01-01在react中使用highlight.js將頁面上的代碼高亮的方法
本文通過 highlight.js 庫實(shí)現(xiàn)對(duì)文章正文 HTML 中的代碼元素自動(dòng)添加語法高亮,具有一定的參考價(jià)值,感興趣的可以了解一下2022-01-01React 中常用的幾種路由跳轉(zhuǎn)方式小結(jié)
基本路由跳轉(zhuǎn)是最常見的一種方式,下面介紹React 中常用的幾種路由跳轉(zhuǎn)方式,感興趣的朋友一起看看吧2023-12-12基于react框架使用的一些細(xì)節(jié)要點(diǎn)的思考
下面小編就為大家?guī)硪黄趓eact框架使用的一些細(xì)節(jié)要點(diǎn)的思考。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-05-05