react编码练习(更新中)
1.使用react实现一个计数器
以下是使用react和tailwind去实现的计数器
思路非常简单:需求就是实现计数的效果
数据为count 逻辑为increment decrement reset 然后完成数据、逻辑与UI的绑定即可
tailwind
tailwind的基础使用:
1.layout 布局
flex flex-col默认横轴为主轴,col设主轴为y轴 items-center justify-center x/y轴的居中 space-x/y-<size> flex元素的距离设置
2.font
font-<family> font-<weight> text-color-<shade> text-<size>(xl) text-center 文字的类别 质量 颜色深度 大小 文字居中
3.box
m p trbl x/y 外边距与内边距
4.animation
hover:bg-color-<shade> 鼠标移动,背景颜色深度
focus:outline-none 移除按钮原本样式
focus:ring-<size>/color-<shade>/offset-<size>颜色深度与内偏移量
transiton 动画过渡,结合hover/focus实现平滑而不是突然变化
ease-in-out 中间变化快 两边变化慢
duration-<ms> 动画持续时间
react
import React, { useState } from 'react';
function App() { // 修复:函数声明需要使用圆括号 ()
// 设置count状态
const [count, setCount] = useState(0); // 修复:移除了类型注释 <number,number>
// 使用函数式写法,获取到最新的state
const incrementCount = () => { // 修复:箭头函数语法
setCount(prevCount => prevCount + 1); // 修复:使用 prevCount + 1 而不是 prevCount++
};
// 考虑特殊情况,计数器不能小于0
const decrementCount = () => { // 修复:箭头函数语法
setCount(prevCount => Math.max(0, prevCount - 1)); // 修复:使用 prevCount - 1 而不是 prevCount--
};
const resetCount = () => { // 修复:箭头函数语法
setCount(0); // 修复:直接设置0,而不是赋值操作
};
return (
<main className="flex flex-col items-center justify-center min-h-screen bg-gray-100 p-4 font-inter"> {/* 修复:class 改为 className,并添加基础样式 */}
<h1 className="text-3xl font-bold text-gray-800 mb-6">React 计数器</h1> {/* 添加标题和样式 */}
<p className="text-6xl font-extrabold text-blue-600 mb-8"> {/* 修复:移除了多余的 {{ }},直接使用 {count} */}
{count}
</p>
<div className="flex space-x-4"> {/* 按钮布局 */}
<button
onClick={incrementCount}
className="px-6 py-3 bg-green-500 text-white font-semibold rounded-lg shadow-md hover:bg-green-600 focus:outline-none focus:ring-2 focus:ring-green-500 focus:ring-offset-2 transition ease-in-out duration-150"
>
增加
</button>
<button
onClick={decrementCount}
className="px-6 py-3 bg-red-500 text-white font-semibold rounded-lg shadow-md hover:bg-red-600 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2 transition ease-in-out duration-150"
>
减少
</button>
<button
onClick={resetCount}
className="px-6 py-3 bg-gray-500 text-white font-semibold rounded-lg shadow-md hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-gray-500 focus:ring-offset-2 transition ease-in-out duration-150"
>
重置
</button>
</div>
</main>
);
}
export default App;
2.使用react实现一个todolist
import React, { useState } from 'react';
function App() {
// 用于添加新事项的输入框值
const [newItem, setNewItem] = useState('');
// 存储所有待办事项的列表
const [todoList, setTodoList] = useState(['学习 React Hook', '复习 Vue 3', '准备实习面试']);
// 用于编辑功能的状态
const [editingIndex, setEditingIndex] = useState(null); // 存储当前正在编辑的事项的索引,null 表示没有事项在编辑
const [editingText, setEditingText] = useState(''); // 存储当前正在编辑的事项的临时文本
// 处理添加新事项输入框内容变化的函数
const handleNewItemChange = (event) => {
setNewItem(event.target.value);
};
// 添加待办事项的函数
const addItem = () => {
if (newItem.trim()) { // 确保输入不为空
setTodoList([...todoList, newItem.trim()]); // 使用展开运算符添加新项
setNewItem(''); // 清空输入框
}
};
// 删除待办事项的函数
const removeItem = (indexToRemove) => {
// 使用 filter 创建一个新数组,排除掉要删除的项
const updatedList = todoList.filter((_, i) => i !== indexToRemove);
setTodoList(updatedList);
// 如果删除的是当前正在编辑的事项,则重置编辑状态
if (editingIndex === indexToRemove) {
cancelEdit();
} else if (editingIndex !== null && editingIndex > indexToRemove) {
// 如果删除的事项在正在编辑的事项之前,需要调整 editingIndex
setEditingIndex(editingIndex - 1);
}
};
// 进入编辑模式的函数
const editItem = (index, itemText) => {
setEditingIndex(index); // 设置当前编辑的索引
setEditingText(itemText); // 将当前事项的文本赋值给编辑输入框
};
// 处理编辑输入框内容变化的函数
const handleEditingTextChange = (event) => {
setEditingText(event.target.value);
};
// 保存编辑的函数
const saveEdit = () => {
if (editingIndex !== null && editingText.trim()) {
// 创建一个新数组,更新对应索引的待办事项文本
const updatedList = todoList.map((item, i) =>
i === editingIndex ? editingText.trim() : item
);
setTodoList(updatedList);
// 重置编辑状态
setEditingIndex(null);
setEditingText('');
} else if (editingIndex !== null && !editingText.trim()) {
// 如果编辑后内容为空,选择删除该事项
removeItem(editingIndex);
// 因为 removeItem 内部会处理编辑状态的重置,这里不需要重复调用 cancelEdit
}
};
// 取消编辑的函数
const cancelEdit = () => {
setEditingIndex(null); // 重置编辑索引
setEditingText(''); // 清空编辑文本
};
return (
<div className="p-4 max-w-md mx-auto bg-white rounded-xl shadow-md space-y-4 font-inter">
<h1 className="text-2xl font-bold text-gray-800 text-center">我的待办事项 (React CRUD)</h1>
{/* 添加事项区域 */}
<div className="flex space-x-2">
<input
type="text"
className="flex-grow p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
value={newItem}
onChange={handleNewItemChange}
onKeyPress={(e) => {
if (e.key === 'Enter') {
addItem();
}
}}
placeholder="添加新的待办事项"
/>
<button
onClick={addItem}
className="px-4 py-2 bg-blue-600 text-white font-semibold rounded-md shadow-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2"
>
添加
</button>
</div>
{/* 待办事项列表 (读取/显示功能) */}
<ul className="space-y-2">
{todoList.map((item, index) => (
<li
key={index} // 在 React 循环渲染列表时,key 是非常重要的
className="flex items-center justify-between p-3 bg-gray-100 rounded-md shadow-sm"
>
{/* 条件渲染:根据是否处于编辑模式显示不同内容 */}
{editingIndex === index ? (
// 编辑模式 (Update)
<div className="flex flex-grow items-center">
<input
type="text"
value={editingText}
onChange={handleEditingTextChange}
onKeyPress={(e) => {
if (e.key === 'Enter') {
saveEdit();
} else if (e.key === 'Escape') {
cancelEdit();
}
}}
className="flex-grow p-2 border border-blue-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
<div className="flex space-x-2 ml-2">
<button
onClick={saveEdit}
className="px-3 py-1 bg-green-500 text-white font-semibold rounded-md shadow-sm hover:bg-green-600 focus:outline-none focus:ring-2 focus:ring-green-500 focus:ring-offset-2"
>
保存
</button>
<button
onClick={cancelEdit}
className="px-3 py-1 bg-gray-500 text-white font-semibold rounded-md shadow-sm hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-gray-500 focus:ring-offset-2"
>
取消
</button>
</div>
</div>
) : (
// 显示模式 (Read)
<>
<span className="text-gray-700">{item}</span>
<div className="flex space-x-2">
<button
onClick={() => editItem(index, item)}
className="px-3 py-1 bg-yellow-500 text-white font-semibold rounded-md shadow-sm hover:bg-yellow-600 focus:outline-none focus:ring-2 focus:ring-yellow-500 focus:ring-offset-2"
>
编辑
</button>
<button
onClick={() => removeItem(index)}
className="px-3 py-1 bg-red-500 text-white font-semibold rounded-md shadow-sm hover:bg-red-600 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2"
>
删除
</button>
</div>
</>
)}
</li>
))}
</ul>
</div>
);
}
export default App;