发布于 2026-01-06 4 阅读
0

React Fragments – 什么是 Fragments?为什么使用 Fragments?如何使用?问题、解决方案、典型用例、我应该使用 Fragments 吗?总结

React Fragments——是什么、为什么、如何做

问题

解决方案

典型用例

我应该使用片段吗?

总结

React Fragments是在React 16.2.0中引入的。尽管它们已经存在一段时间了,但我交谈过的许多React开发人员还没有开始使用它们,而造成这种情况的首要原因通常是他们听说过它们,但还没有抽出时间去学习它们。

那么它们是什么?你该开始使用它们吗?后一个问题的答案是肯定的,而第一个问题的答案正是这篇博文将要告诉你的。

你是 React 新手吗?一定要阅读我的文章《每个 React 初学者都应该知道的 6 件事》

问题

正如 React.js 文档所述,React 中常见的模式是组件返回多个元素。通常,这些元素会被包裹在一个例如 div 标签内。在大多数情况下,这个包裹元素是“无关紧要的”,添加它仅仅是因为 React 组件要求你只能返回一个元素。这种行为会导致无用的标记,有时甚至会渲染出无效的 HTML,这是不好的。

例如,我们可以创建一个名为 Table 的组件来渲染 HTML 表格,然后在表格内部使用另一个名为 Columns 的组件来渲染列。它看起来大概是这样的。

class Table extends React.Component {
  render() {
    return (
      <table>
        <tr>
          <Columns />
        </tr>
      </table>
    );
  }
}
class Columns extends React.Component {
  render() {
    return (
      <div>
        <td>Hello</td>
        <td>World</td>
      </div>
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

这将导致渲染出无效的 HTML,因为 Columns 组件中的包装 div 被渲染在<tr>.

<table>
  <tr>
    <div>
      <td>Hello</td>
      <td>World</td>
    </div>
  </tr>
</table>
Enter fullscreen mode Exit fullscreen mode

解决方案

解决方案正如你所料,就是 Fragment!React Fragment 允许你将一系列子元素分组,而无需向 DOM 添加额外的节点,因为 Fragment 本身并不渲染到 DOM 中。所以,我们基本上用 React.Fragment 代替了通常会用到的 div 元素。

我们可以使用带有<React.Fragments>语法的片段。因此,我们可以按如下方式编写 Columns 组件。

class Columns extends React.Component {
  render() {
    return (
      <React.Fragment>
        <td>Hello</td>
        <td>World</td>
      </React.Fragment>
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

现在表格组件将渲染以下HTML代码。

<table>
  <tr>
    <td>Hello</td>
    <td>World</td>
  </tr>
</table>
Enter fullscreen mode Exit fullscreen mode

也可以使用类似空标签的简短语法来声明片段。以下是一个示例。

class Columns extends React.Component {
  render() {
    return (
      <>
        <td>Hello</td>
        <td>World</td>
      </>
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

典型用例

返回多个元素

React Fragment 最常见的用途可能是在需要返回多个元素时。使用 Fragment 可以轻松实现这一点,而且无需像传统方式那样使用 div 来包裹元素。

class Application extends React.Component {
  render() {
    return (
      <React.Fragment>
        <Header />
        <Content />
        <Footer />
      </React.Fragment>
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

条件渲染

React Fragment 也可用于条件渲染元素。它们可以简化元素组的渲染过程,而无需添加额外的标记。

class LoginForm extends React.Component {
  render() {
    return (
      <form>
        {this.props.isLoggedIn ? (
            <React.Fragment>
              <h3>Welcome</h3>
              <p>You are logged in!</p>
            </React.Fragment>
        ) : (
            <React.Fragment>
              <h3>Login</h3>
              <label for="username">Username</label><br/>
              <input type="text" id="username" /><br/>
              <label for="password">Password</label><br/>
              <input type="password" id="password" /><br/>
              <input type="submit" value="Login" />
            </React.Fragment>
        )}
      </form>
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

数组

在渲染数组时,片段也能帮上忙,因为片段可以拥有 key 属性!假设你有一个用户对象数组,想要渲染数组中的所有用户。你需要为每个用户设置 key 属性,所以通常需要使用类似 div 的元素来包裹用户信息。但是,由于片段可以拥有 key 属性,你可以直接使用片段并为其设置 key 属性,这样就无需添加任何额外的标记。

class UserList extends React.Component {
  users = [
    {
      id: 1,
      name: "Jack Bauer",
      email: "jack.bauer@ctu.gov",
      phone: "+358509283928"
    },
    {
      id: 2,
      name: "Tony Almeida",
      email: "tony.almeida@ctu.gov",
      phone: "+358508829378"
    },
    {
      id: 3,
      name: "Chloe O'brian",
      email: "chloe.obrian@ctu.gov",
      phone: "+358508899012"
    }
  ];
  render() {
    return (
      <React.Fragment>
        {this.users.map(user => (
          <React.Fragment key={user.id}>
            <h2>{user.name}</h2>
            <p>{user.email}</p>
            <p>{user.phone}</p>
          </React.Fragment>
        ))}
      </React.Fragment>
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

我应该使用片段吗?

那么,使用片段(fragment)来代替例如包装 div 元素是否值得呢?

Dan Abramov在StackOverflow上回答了这个问题

  • 它速度略快,内存占用更少(无需创建额外的 DOM 节点)。这仅在非常大或非常深的树状结构中才真正有优势,但应用程序性能通常会因“千刀万剐”而下降。而这种方法减少了一次切割。
  • 一些 CSS 机制,如 Flexbox 和 CSS Grid,具有特殊的父子关系,在中间添加 div 会使在提取逻辑组件时难以保持所需的布局。
  • DOM 检查器界面更简洁了。🙂

因此,片段消除了可能导致无效 HTML 和组件样式问题的包装 div,再加上它们速度更快、DOM 更简洁,我认为它们值得使用。

总结

你对 React Fragment 有什么看法?你在自己的项目中使用过吗?请在下方留言,我很想听听你的想法!

别忘了订阅我的电子报,随时了解现代网页开发的最新资讯和文章。我还会为电子报订阅用户分享独家技巧和秘诀!点击此处订阅。


原文发表于tuomokankaanpaa.com,日期为 2019 年 10 月 6 日。

文章来源:https://dev.to/tumee/react-fragments-what-why-how-2kh1