当前位置: 首页 > news >正文

第4课:列表渲染与条件渲染

第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>
        <button
          className={filter === 'active' ? 'active' : ''}
          onClick={() => setFilter('active')}
        >
          未完成 ({tasks.filter(t => !t.completed).length})
        </button>
        <button
          className={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);
}

四、练习任务

  1. 实现分类过滤功能:

    • 添加「工作」「学习」「生活」分类筛选
    • 显示每个分类的任务数量
    • 支持多选过滤
  2. 增强空状态提示:

    • 不同过滤状态显示不同的提示文案
    • 添加「新建任务」按钮到空状态区域
  3. 实现动画删除效果:

    • 点击删除时添加渐出动画
    • 使用CSS transition或react-transition-group
  4. (挑战)添加排序功能:

    • 支持按优先级排序
    • 支持按创建时间排序
    • 在卡片上显示创建时间

五、常见问题解答

Q: 为什么列表项会出现奇怪的重绘行为?
A: 检查:

  1. key是否稳定唯一
  2. 是否直接修改了状态数组
  3. 组件是否做了不必要的重新渲染

Q: 条件渲染导致布局跳动怎么办?
A: 解决方法:

  1. 使用CSS opacity过渡
  2. 保持DOM结构稳定(用空元素占位)
  3. 使用动画库处理过渡效果

Q: 如何处理复杂的条件组合?
A: 推荐方案:

  1. 提前计算渲染条件
  2. 使用策略模式封装条件判断
  3. 考虑使用useMemo优化计算

六、课程总结

本节重点:

  • 列表渲染的key最佳实践
  • 四种条件渲染模式的应用场景
  • 复杂数据结构的可视化呈现
  • 交互体验的全面优化

能力提升:

  • 列表性能优化意识
  • 条件逻辑的优雅处理
  • 用户反馈的视觉设计

课后作业

  1. 完成分类过滤功能的实现
  2. 为任务添加创建时间字段并显示
  3. 尝试使用CSS Grid实现响应式任务列表布局

附加资源

  • React列表渲染官方指南
  • key的重要性深度解析
  • CSS过渡动画教程
  • react-transition-group文档
# 保存当前进度
git add .
git commit -m "feat: 完成列表渲染与条件渲染优化"

相关文章:

  • Diffusion Policy Visuomotor Policy Learning via Action Diffusion官方项目解读(二)(2)
  • Java 集合框架与 Stream 流深入剖析(重点详细讲解)
  • langchain实现基于语义分块的文档处理技术semantic-chunker
  • 小飞电视 2.7.0 | 高清秒播无卡顿的电视直播软件
  • 大模型部署实践第一天——基于Colab体验完整部署流程
  • C语言中单向链表:创建节点与插入新节点
  • lerobot[部署,元数据集,加载数据集]
  • Java学习总结-线程同步
  • keil5忽略警告
  • S32K144入门笔记(二十五):FlexCAN初始化序列
  • LeetCode 1169 查询无效交易
  • 【嵌入式系统设计师】知识点:第3章 嵌入式硬件设计
  • HCIP【路由策略技术(详解)】
  • 1️⃣ 智能体基础入门教学(2025年全新版本)
  • 国内 windows powershell 安装 scoop
  • Llama 4 家族:原生多模态 AI 创新的新时代开启
  • 消息队列基础概念及选型,常见解决方案包括消息可靠性、消息有序、消息堆积、重复消费、事务消息
  • 企业网站模板源码 免费网站模板下载
  • 基础算法模拟(超详细)
  • 【spring02】Spring 管理 Bean-IOC,基于 XML 配置 bean
  • 铁路建设网站多少/今日新闻10条简短
  • 免费的网站给一个/友情链接查询工具
  • 十堰响应式网站建设/池州网络推广
  • dede网站404怎么做/百度搜索排名优化
  • 宜兴建设局拍卖房产的网站/海外推广方法有哪些
  • 物流公司网站建设/郑州网站设计有哪些