株洲网上购房节爱站seo查询
第4课:列表渲染与条件渲染
学习目标
- 掌握列表渲染的进阶技巧
- 理解
key
属性的核心作用 - 灵活运用多种条件渲染方式
- 优化任务列表的交互体验
一、列表渲染优化实践
1. 复杂数据结构渲染
更新App.js
中的初始状态:
const [tasks, setTasks] = useState([{id: 1,title: '学习React基础',description: '完成组件和状态管理学习',completed: false,priority: 'high',category: '学习'},{id: 2,title: '项目会议',description: '下午3点团队进度同步',completed: true,priority: 'medium',category: '工作'}
]);
2. 增强型TaskCard组件
function TaskCard({ task, onToggle, onDelete }) {const getPriorityColor = () => {switch(task.priority) {case 'high': return '#ff4444';case 'medium': return '#ffbb33';default: return '#00C851';}};return (<div className={`task-card ${task.completed ? 'completed' : ''}`}><div className="task-header"><span className="priority-dot" style={{ backgroundColor: getPriorityColor() }}/><h3>{task.title}</h3><span className="category-tag">{task.category}</span></div><p className="task-description">{task.description}</p><div className="task-footer"><button onClick={onToggle}className={`status-btn ${task.completed ? 'completed' : ''}`}>{task.completed ? '✅ 已完成' : '⏳ 进行中'}</button><button onClick={onDelete}className="delete-btn">🗑️ 删除</button></div></div>);
}
3. Key的重要性示例
错误示例:
{tasks.map((task, index) => (<TaskCard key={index} task={task} />
))}
正确实践:
{tasks.map(task => (<TaskCard key={task.id}task={task}onToggle={() => toggleTask(task.id)}onDelete={() => deleteTask(task.id)}/>
))}
为什么重要:
- 帮助React识别元素变化
- 维持组件状态稳定性
- 提升列表更新性能
二、条件渲染的四种方式
1. && 运算符
{!tasks.length && (<div className="empty-state"><img src="/empty.svg" alt="空状态" /><p>暂时没有任务,添加一个吧!</p></div>
)}
2. 三元表达式
<div className="task-stats">总计任务: {tasks.length}{tasks.length > 0 ? (<span>(已完成: {tasks.filter(t => t.completed).length})</span>) : null}
</div>
3. 组件外返回
function TaskList({ tasks }) {if (!tasks.length) {return <EmptyState />;}return (<div className="task-list">{tasks.map(task => (<TaskCard key={task.id} task={task} />))}</div>);
}
4. 枚举对象
const priorityLabels = {high: { text: '紧急', color: 'red' },medium: { text: '一般', color: 'orange' },low: { text: '低', color: 'green' }
};// 在组件中使用
<span style={{ color: priorityLabels[task.priority].color }}>{priorityLabels[task.priority].text}
</span>
三、实战:增强任务列表
1. 添加过滤功能
function App() {const [filter, setFilter] = useState('all');const filteredTasks = tasks.filter(task => {if (filter === 'completed') return task.completed;if (filter === 'active') return !task.completed;return true;});return (<div className="App"><div className="filters"><button className={filter === 'all' ? 'active' : ''}onClick={() => setFilter('all')}>全部 ({tasks.length})</button><buttonclassName={filter === 'active' ? 'active' : ''}onClick={() => setFilter('active')}>未完成 ({tasks.filter(t => !t.completed).length})</button><buttonclassName={filter === 'completed' ? 'active' : ''}onClick={() => setFilter('completed')}>已完成 ({tasks.filter(t => t.completed).length})</button></div><TaskList tasks={filteredTasks} /></div>);
}
2. 样式优化 (App.css)
/* 过滤按钮 */
.filters {display: flex;gap: 10px;margin-bottom: 20px;
}.filters button {padding: 8px 16px;border: 1px solid #ddd;border-radius: 20px;background: white;cursor: pointer;transition: all 0.3s;
}.filters button.active {background: #2196F3;color: white;border-color: #2196F3;
}/* 空状态 */
.empty-state {text-align: center;padding: 40px;opacity: 0.6;
}.empty-state img {width: 150px;margin-bottom: 20px;
}/* 任务卡片增强 */
.task-header {display: flex;align-items: center;gap: 10px;margin-bottom: 12px;
}.priority-dot {width: 10px;height: 10px;border-radius: 50%;
}.category-tag {background: #e0e0e0;padding: 2px 8px;border-radius: 4px;font-size: 0.8em;
}.task-footer {display: flex;justify-content: space-between;align-items: center;margin-top: 15px;
}.delete-btn {background: none;border: none;color: #ff4444;cursor: pointer;transition: transform 0.2s;
}.delete-btn:hover {transform: scale(1.1);
}/* 动画效果 */
.task-card {transition: transform 0.3s, box-shadow 0.3s;
}.task-card:hover {transform: translateY(-2px);box-shadow: 0 4px 12px rgba(0,0,0,0.1);
}
四、练习任务
-
实现分类过滤功能:
- 添加「工作」「学习」「生活」分类筛选
- 显示每个分类的任务数量
- 支持多选过滤
-
增强空状态提示:
- 不同过滤状态显示不同的提示文案
- 添加「新建任务」按钮到空状态区域
-
实现动画删除效果:
- 点击删除时添加渐出动画
- 使用CSS transition或react-transition-group
-
(挑战)添加排序功能:
- 支持按优先级排序
- 支持按创建时间排序
- 在卡片上显示创建时间
五、常见问题解答
Q: 为什么列表项会出现奇怪的重绘行为?
A: 检查:
- key是否稳定唯一
- 是否直接修改了状态数组
- 组件是否做了不必要的重新渲染
Q: 条件渲染导致布局跳动怎么办?
A: 解决方法:
- 使用CSS opacity过渡
- 保持DOM结构稳定(用空元素占位)
- 使用动画库处理过渡效果
Q: 如何处理复杂的条件组合?
A: 推荐方案:
- 提前计算渲染条件
- 使用策略模式封装条件判断
- 考虑使用useMemo优化计算
六、课程总结
本节重点:
- 列表渲染的key最佳实践
- 四种条件渲染模式的应用场景
- 复杂数据结构的可视化呈现
- 交互体验的全面优化
能力提升:
- 列表性能优化意识
- 条件逻辑的优雅处理
- 用户反馈的视觉设计
课后作业
- 完成分类过滤功能的实现
- 为任务添加创建时间字段并显示
- 尝试使用CSS Grid实现响应式任务列表布局
附加资源
- React列表渲染官方指南
- key的重要性深度解析
- CSS过渡动画教程
- react-transition-group文档
# 保存当前进度
git add .
git commit -m "feat: 完成列表渲染与条件渲染优化"