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

