太原营销型网站,用手机做app用什么软件最好,郑州技术支持seo,响应式网站样式图怎么做1. 初始化notes
以下这段代码完成了这些操作#xff1a;
调用 localStorage.getItem(notes) 从浏览器的本地存储中获取名为 “notes” 的数据。使用 JSON.parse 将获取到的字符串解析成数组。如果本地存储中没有 “notes” 数据#xff08;返回值为 null#…1. 初始化notes
以下这段代码完成了这些操作
调用 localStorage.getItem(notes) 从浏览器的本地存储中获取名为 “notes” 的数据。使用 JSON.parse 将获取到的字符串解析成数组。如果本地存储中没有 “notes” 数据返回值为 null则默认将 notes 设置为空数组 []。
const [notes, setNotes] React.useState(JSON.parse(localStorage.getItem(notes)) || [])useState钩子
useState 是 React 的一个钩子用于在函数组件中引入状态。 它返回一个数组有两个元素
当前状态值这里是 notes。更新状态的函数这里是 setNotes。
localStorage
localStorage 是浏览器提供的 API用于在本地存储键值对数据。localStorage.getItem(notes) 从 localStorage 中获取键为 “notes” 的数据返回的结果是一个字符串。
JSON.parse
localStorage 中存储的所有数据都是字符串。 JSON.parse 将字符串解析为 JavaScript 对象。
如果存储的数据是一个 JSON 字符串例如“[1, 2, 3]”调用 JSON.parse 后会得到 [1, 2, 3]。
|| 运算符
|| 是逻辑或运算符用来提供一个默认值。如果 localStorage.getItem(notes) 返回 null即没有找到 “notes” 键JSON.parse(localStorage.getItem(notes)) 的结果会是 null。在这种情况下表达式的右侧[]会被返回表示 notes 的初始值是一个空数组。
2. 每次notes发生改变时将notes保存到localStorage React.useEffect(() {localStorage.setItem(notes, JSON.stringify(notes))}, [notes])useEffect 是 React 的一个钩子用于在函数组件中处理副作用。
副作用通常指与组件渲染逻辑无关的行为例如数据获取、订阅、手动 DOM 操作、或者日志记录等。
它的语法如下
React.useEffect(effectFunction, dependencies);effectFunction 是一个函数在特定条件下运行。 dependencies 是一个数组控制 effectFunction 的运行时机。
localStorage.setItem 是浏览器提供的 API用于向 localStorage 中存储键值对。 它接受两个参数
键存储数据的名称这里是 “notes”。值存储的具体数据必须是字符串。
JSON.stringify(notes)
将 notes 转换为 JSON 格式的字符串因为 localStorage 只能存储字符串数据。
当组件渲染后并且 notes 发生变化时
useEffect 会被触发。localStorage.setItem(“notes”, JSON.stringify(notes)) 将最新的 notes 数组保存到本地存储中。
如果 notes 没有变化
即使组件重新渲染useEffect 不会运行因为 notes 的值没有改变。
3. 什么是 Lazy State Initialization?
通常情况下useState 的初始值是直接计算出来的
const [state, setState] React.useState(computeInitialState());这里 computeInitialState() 会在组件每次渲染时立即执行即使结果只需要在初次渲染时使用。如果 computeInitialState 是一个复杂的计算函数就会浪费性能。
为了解决这个问题React 提供了一种惰性初始化的方法通过向 useState 传递一个函数而不是直接传递计算结果。这种函数只会在组件第一次渲染时执行之后不会再次调用。
惰性初始化
const [state, setState] React.useState(() computeInitialState());当传递一个函数给 useState 时React 只会在组件初次渲染时调用这个函数来计算初始状态。后续的状态更新不再调用此函数。
4. 在React中实现删除笔记的操作
button classNamedelete-btnonClick{(event) props.deleteNote(event, note.id)}
i classNamegg-trash trash-icon/i
/buttonbutton 元素
HTML 的按钮标签用于定义一个可点击的交互元素。在 React 中 可以绑定事件和自定义属性并触发相关的事件处理程序。
回调函数中的 (event) props.deleteNote(event, note.id) 是一个箭头函数执行时调用 props.deleteNote 方法并将两个参数传递给它
event原生的点击事件对象提供有关点击的信息如目标元素、鼠标位置等。note.id当前笔记的唯一标识符用于指定要删除的具体笔记。
i 是 HTML 的行内元素通常用作图标的占位符。 function deleteNote(event, noteId){event.stopPropagation()setNotes(oldNotes oldNotes.filter(note note.id ! noteId))}event.stopPropagation() 作用
阻止事件从当前元素传播到父元素或其他祖先元素即阻止事件冒泡。防止删除按钮的点击事件触发父组件的其他事件处理逻辑如整个笔记项的点击事件。
场景举例: 假设笔记项的外层组件有一个点击事件绑定
div onClick{() console.log(Note clicked!)}button onClick{(event) deleteNote(event, noteId)}Delete/button
/div
如果没有 event.stopPropagation()
点击删除按钮时既会触发 deleteNote又会触发外层 div 的 onClick。
有了 event.stopPropagation()
点击删除按钮时只会触发 deleteNote。
箭头函数 oldNotes oldNotes.filter(...) setNotes 接收一个更新函数该函数的参数是当前的状态值 oldNotes。 filter 方法
返回一个新数组其中包含满足条件的所有元素。条件保留 id 不等于 noteId 的笔记即删除 noteId 对应的笔记。
完整逻辑 通过 filter 遍历 oldNotes 数组
如果 note.id ! noteId该笔记被保留。如果 note.id noteId该笔记被过滤掉。
返回的新数组赋值给 notes并触发组件重新渲染。
5. 删除按钮的CSS实现
.delete-btn {display: none;background: none;border: none;
}作用
定义删除按钮的初始样式默认情况下按钮是隐藏的。
属性解释 display: none; 隐藏元素按钮不占据布局空间不可见。 background: none; 移除按钮的默认背景样式。 border: none; 移除按钮的默认边框。
.title:hover .delete-btn {display: block;
}作用
当用户将鼠标悬停在 .title 元素上时其子元素 .delete-btn 显示出来。
属性解释 display: block;
让 .delete-btn 可见并以块级元素形式显示。 .delete-btn
表示只选择直接子元素 .delete-btn避免影响其他嵌套更深的 .delete-btn。
实现逻辑
通过伪类 :hover动态切换按钮的显示状态提供更好的用户交互体验。
.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;
控制元素的宽高计算方式包含内边距和边框。
position: relative;
定义元素为相对定位用于配合子元素的绝对定位。
transform: scale(var(--ggs,1));
使用 CSS 变量 --ggs 控制缩放比例默认为 1。
width: 10px; height: 12px;
定义垃圾桶的宽度和高度。
border: 2px solid transparent;
设置透明的边框。
box-shadow 为垃圾桶形状添加外边框和内部边框
0 0 0 2px外部边框2px 宽。inset -2px 0 0 和 inset 2px 0 0内部分隔线。
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;
使用绝对定位将盖子放置在垃圾桶顶部。
总结垃圾桶图标的整体实现
.gg-trash 是垃圾桶的主体包括边框、阴影等基础结构。::after 添加横梁垃圾桶盖的下部分。::before 添加盖子顶部的弯曲结构。
结合这些样式实现了一个完整的垃圾桶图标。
交互效果总结
.delete-btn 默认隐藏用户鼠标悬停在 .title 上时显示。鼠标悬停时垃圾桶图标变为可点击状态通过样式 cursor: pointer 提供视觉提示。
6. 查找当前笔记id
const [currentNoteId, setCurrentNoteId] React.useState((notes[0]?.id) || )
const currentNote notes.find(note note.id currentNoteId) || notes[0]React.useState
定义一个状态变量 currentNoteId 和其对应的更新函数 setCurrentNoteId。
notes[0]?.id
通过可选链操作符 (?.)尝试访问数组 notes 中第一项的 id。如果 notes 数组为空或者 notes[0] 为 undefinednotes[0]?.id 返回 undefined 而不会报错。
|| 如果 notes[0]?.id 为 undefinedcurrentNoteId 的初始值设置为空字符串 。
效果
如果 notes 数组非空currentNoteId 的初始值是第一项笔记的 id。如果 notes 数组为空currentNoteId 的初始值是 “”。
notes.find(note note.id currentNoteId)
使用 Array.prototype.find() 方法在 notes 数组中查找 id 等于 currentNoteId 的笔记。find 方法返回第一个满足条件的元素。如果没有找到匹配的元素返回 undefined。
|| notes[0] 如果没有找到匹配的笔记即 find 返回 undefined使用 || 提供默认值返回 notes[0]数组的第一项。