MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

React 使用列表渲染结合条件展示数据

2023-03-156.6k 阅读

React 列表渲染基础

在 React 中,列表渲染是一项非常基础且重要的功能。它允许我们将数据集合以列表的形式展示在页面上。通常,我们会使用 JavaScript 的数组来存储数据,然后通过 React 的特定语法将数组中的每个元素渲染为页面上的一个组件实例。

使用 map 方法进行列表渲染

在 React 中,最常用的列表渲染方式是使用数组的 map 方法。map 方法会遍历数组的每个元素,并返回一个新的数组,新数组的元素是原数组元素经过特定函数处理后的结果。在 React 中,我们利用 map 方法将数组中的每个数据元素转换为对应的 React 组件。

例如,假设有一个包含水果名称的数组:

import React from 'react';

function FruitList() {
  const fruits = ['apple', 'banana', 'cherry'];
  const fruitElements = fruits.map((fruit) => <li>{fruit}</li>);
  return <ul>{fruitElements}</ul>;
}

export default FruitList;

在上述代码中,我们定义了一个 FruitList 组件,该组件内部有一个 fruits 数组。通过 map 方法,我们将每个水果名称转换为一个 <li> 元素,最后将所有 <li> 元素放在一个 <ul> 元素中进行渲染。

key 属性的重要性

当使用 map 方法进行列表渲染时,为每个渲染的元素添加一个 key 属性是非常重要的。key 是 React 用于追踪哪些列表项被修改、添加或删除的一个特殊属性。

例如,修改上面的代码添加 key 属性:

import React from 'react';

function FruitList() {
  const fruits = ['apple', 'banana', 'cherry'];
  const fruitElements = fruits.map((fruit, index) => <li key={index}>{fruit}</li>);
  return <ul>{fruitElements}</ul>;
}

export default FruitList;

在这里,我们使用数组元素的索引 index 作为 key。虽然在简单情况下使用索引作为 key 是可行的,但在更复杂的场景下,比如列表项可能会重新排序、添加或删除时,最好使用数据项的唯一标识符作为 key。例如,如果我们的 fruits 数组是一个包含对象的数组,每个对象有一个唯一的 id 属性,那么应该这样设置 key

import React from 'react';

function FruitList() {
  const fruits = [
    { id: 1, name: 'apple' },
    { id: 2, name: 'banana' },
    { id: 3, name: 'cherry' }
  ];
  const fruitElements = fruits.map((fruit) => <li key={fruit.id}>{fruit.name}</li>);
  return <ul>{fruitElements}</ul>;
}

export default FruitList;

使用唯一标识符作为 key 可以帮助 React 更高效地更新 DOM,避免不必要的重新渲染。

React 条件展示数据

除了列表渲染,条件展示数据也是前端开发中常见的需求。在 React 中,有多种方式可以实现条件展示。

使用 if 语句进行条件展示

最直接的方式就是使用 JavaScript 的 if 语句。例如,我们有一个组件根据用户是否登录来显示不同的内容:

import React, { useState } from'react';

function UserInfo() {
  const [isLoggedIn, setIsLoggedIn] = useState(false);

  let content;
  if (isLoggedIn) {
    content = <p>Welcome, user!</p>;
  } else {
    content = <p>Please log in.</p>;
  }

  return <div>{content}</div>;
}

export default UserInfo;

在上述代码中,我们使用 useState 钩子来管理用户登录状态 isLoggedIn。根据 isLoggedIn 的值,通过 if - else 语句来决定 content 的内容,最后将 content 渲染到页面上。

使用逻辑与运算符(&&)进行条件展示

逻辑与运算符 && 也可以用于条件展示。它的原理是如果 && 左边的表达式为真,就会返回右边的表达式;如果左边的表达式为假,就会返回左边的表达式。

例如,我们可以修改上面的代码使用 && 来实现相同的效果:

import React, { useState } from'react';

function UserInfo() {
  const [isLoggedIn, setIsLoggedIn] = useState(false);

  return (
    <div>
      {isLoggedIn && <p>Welcome, user!</p>}
      {!isLoggedIn && <p>Please log in.</p>}
    </div>
  );
}

export default UserInfo;

这里,当 isLoggedIntrue 时,isLoggedIn && <p>Welcome, user!</p> 会返回 <p>Welcome, user!</p> 并渲染;当 isLoggedInfalse 时,!isLoggedIn && <p>Please log in.</p> 会返回 <p>Please log in.</p> 并渲染。

使用三元运算符进行条件展示

三元运算符 condition? expressionIfTrue : expressionIfFalse 也常用于条件展示。它根据条件 condition 的真假来决定返回 expressionIfTrue 还是 expressionIfFalse

例如,再次修改上述代码使用三元运算符:

import React, { useState } from'react';

function UserInfo() {
  const [isLoggedIn, setIsLoggedIn] = useState(false);

  const content = isLoggedIn? <p>Welcome, user!</p> : <p>Please log in.</p>;

  return <div>{content}</div>;
}

export default UserInfo;

在这个例子中,根据 isLoggedIn 的值,三元运算符决定 content 的值,然后将 content 渲染到页面上。

React 使用列表渲染结合条件展示数据

在实际应用中,我们常常需要将列表渲染和条件展示结合起来。例如,我们有一个任务列表,需要根据任务的完成状态来显示不同的样式。

根据条件渲染列表项的样式

假设我们有一个任务列表,每个任务是一个对象,包含 idtitlecompleted 三个属性。我们要根据 completed 属性来决定任务列表项的文本样式。

import React from'react';

function TaskList() {
  const tasks = [
    { id: 1, title: 'Learn React', completed: true },
    { id: 2, title: 'Build a project', completed: false },
    { id: 3, title: 'Deploy the app', completed: true }
  ];

  const taskElements = tasks.map((task) => {
    const style = task.completed? { textDecoration: 'line - through' } : {};
    return <li key={task.id} style={style}>{task.title}</li>;
  });

  return <ul>{taskElements}</ul>;
}

export default TaskList;

在上述代码中,我们通过 map 方法遍历 tasks 数组。对于每个任务,根据 completed 属性来设置 style 对象。如果任务已完成,就设置文本装饰为删除线;否则,设置为空样式对象。最后将每个 <li> 元素渲染到页面上。

条件过滤列表项

有时候,我们可能需要根据某个条件过滤列表项,只显示符合条件的项。例如,我们有一个产品列表,只显示库存大于 0 的产品。

import React from'react';

function ProductList() {
  const products = [
    { id: 1, name: 'Product A', stock: 5 },
    { id: 2, name: 'Product B', stock: 0 },
    { id: 3, name: 'Product C', stock: 3 }
  ];

  const inStockProducts = products.filter((product) => product.stock > 0);

  const productElements = inStockProducts.map((product) => <li key={product.id}>{product.name}</li>);

  return <ul>{productElements}</ul>;
}

export default ProductList;

在这段代码中,我们首先使用 filter 方法过滤出 stock 大于 0 的产品,得到 inStockProducts 数组。然后通过 map 方法将这些产品渲染为 <li> 元素并显示在页面上。

多层条件与列表渲染的复杂结合

在更复杂的场景下,可能会有多层条件和列表渲染的嵌套。例如,我们有一个电商订单列表,每个订单包含多个商品。我们要根据订单的状态(已支付、未支付)以及商品的库存情况来显示不同的信息。

import React from'react';

function OrderList() {
  const orders = [
    {
      id: 1,
      status: 'paid',
      products: [
        { id: 11, name: 'Product X', stock: 10 },
        { id: 12, name: 'Product Y', stock: 0 }
      ]
    },
    {
      id: 2,
      status: 'unpaid',
      products: [
        { id: 21, name: 'Product Z', stock: 5 }
      ]
    }
  ];

  const orderElements = orders.map((order) => {
    const productElements = order.products.map((product) => {
      let productInfo;
      if (product.stock > 0) {
        productInfo = <p>{product.name}: In stock</p>;
      } else {
        productInfo = <p>{product.name}: Out of stock</p>;
      }
      return <li key={product.id}>{productInfo}</li>;
    });

    let orderStatusInfo;
    if (order.status === 'paid') {
      orderStatusInfo = <h3>Order {order.id} (Paid)</h3>;
    } else {
      orderStatusInfo = <h3>Order {order.id} (Unpaid)</h3>;
    }

    return (
      <div key={order.id}>
        {orderStatusInfo}
        <ul>{productElements}</ul>
      </div>
    );
  });

  return <div>{orderElements}</div>;
}

export default OrderList;

在这个例子中,我们首先通过 map 方法遍历 orders 数组。对于每个订单,我们再通过 map 方法遍历其 products 数组。在遍历 products 数组时,根据商品的库存情况设置 productInfo。对于订单,根据其状态设置 orderStatusInfo。最后将订单状态信息和商品信息组合起来进行渲染。

动态条件改变列表渲染

我们还可以通过用户交互动态改变条件,从而影响列表的渲染。例如,有一个搜索框,用户输入关键字后,列表只显示包含该关键字的项。

import React, { useState } from'react';

function SearchList() {
  const items = [
    { id: 1, name: 'Apple' },
    { id: 2, name: 'Banana' },
    { id: 3, name: 'Cherry' }
  ];

  const [searchText, setSearchText] = useState('');

  const filteredItems = items.filter((item) =>
    item.name.toLowerCase().includes(searchText.toLowerCase())
  );

  const itemElements = filteredItems.map((item) => <li key={item.id}>{item.name}</li>);

  return (
    <div>
      <input
        type="text"
        placeholder="Search..."
        value={searchText}
        onChange={(e) => setSearchText(e.target.value)}
      />
      <ul>{itemElements}</ul>
    </div>
  );
}

export default SearchList;

在上述代码中,我们使用 useState 钩子来管理搜索框的输入值 searchText。每次用户在搜索框输入内容时,onChange 事件会更新 searchText。然后通过 filter 方法根据 searchText 过滤 items 数组,只保留名称中包含搜索关键字的项。最后将过滤后的项渲染为列表。

性能优化与注意事项

在使用列表渲染结合条件展示数据时,有一些性能优化和注意事项需要关注。

避免不必要的重新渲染

在 React 中,组件的重新渲染可能会导致性能问题。当列表渲染结合条件展示时,如果条件的改变频繁且不必要地触发了列表组件的重新渲染,就需要优化。

例如,在使用 map 方法进行列表渲染时,如果 map 回调函数中返回的元素没有依赖于组件的状态或属性变化,那么可以使用 React.memo 来包裹列表项组件。假设我们有一个简单的列表项组件 ListItem

import React from'react';

const ListItem = React.memo(({ item }) => {
  return <li>{item.name}</li>;
});

export default ListItem;

然后在列表渲染时使用这个组件:

import React from'react';
import ListItem from './ListItem';

function MyList() {
  const items = [
    { id: 1, name: 'Item 1' },
    { id: 2, name: 'Item 2' }
  ];

  const itemElements = items.map((item) => <ListItem key={item.id} item={item} />);

  return <ul>{itemElements}</ul>;
}

export default MyList;

这样,只有当 ListItem 组件的 item 属性发生变化时,ListItem 组件才会重新渲染,避免了不必要的重新渲染。

合理使用 key 属性

前面提到了 key 属性在列表渲染中的重要性。在结合条件展示时,也要确保 key 属性的使用是合理的。如果条件的改变会导致列表项的顺序或内容发生较大变化,不正确的 key 设置可能会导致 React 无法正确识别列表项的更新,从而影响性能。

例如,在条件过滤列表项时,如果过滤后的列表项顺序发生了变化,使用索引作为 key 可能会出现问题。此时,还是应该尽量使用数据项的唯一标识符作为 key,以确保 React 能够高效地更新 DOM。

条件判断的性能优化

在进行条件展示时,尽量简化条件判断的逻辑。复杂的条件判断可能会消耗更多的计算资源,特别是在列表渲染中,每个列表项都可能涉及条件判断。

例如,如果有多个条件嵌套判断,可以尽量合并条件或者使用更简洁的逻辑表达式。同时,如果条件判断的结果是固定的,比如某些条件只在应用初始化时需要判断一次,而不是每次渲染都判断,可以将这些判断逻辑提取到组件的 useEffect 钩子中,并且通过设置适当的依赖项,避免不必要的重复计算。

数据结构的选择

选择合适的数据结构对于列表渲染结合条件展示的性能也很重要。例如,如果经常需要根据某个属性过滤列表项,使用对象数组并结合 filter 方法是比较合适的。但如果需要频繁地插入、删除列表项,并且要保持列表的顺序,使用链表结构可能更合适。不过在 React 中,一般还是以对象数组作为主要的数据存储结构,因为它更方便与 mapfilter 等数组方法结合使用。但在某些特殊场景下,需要根据实际需求考虑更合适的数据结构。

总结

React 中列表渲染结合条件展示数据是一项强大且常用的功能。通过合理运用 map 方法、条件判断语句(如 if&&、三元运算符)以及正确设置 key 属性等,可以实现各种复杂的数据展示需求。同时,注意性能优化和避免常见的错误,能够让我们的应用更加高效和稳定。无论是简单的任务列表,还是复杂的电商订单系统,这些技术都能帮助我们构建出优秀的前端界面。在实际开发中,需要根据具体的业务需求和数据特点,灵活运用这些方法,以达到最佳的开发效果。