为什么 React 16 中的 Fragments 比容器 div 更好?

IT技术 reactjs
2021-03-25 15:46:19

在 React 16.2 中,Fragments添加了改进的支持更多信息可以在 React 的博客文章中找到。

下面的代码我们都很熟悉:

render() {
  return (
    // Extraneous div element :(
    <div>
      Some text.
      <h2>A heading</h2>
      More text.
      <h2>Another heading</h2>
      Even more text.
    </div>
  );
}

是的,我们需要一个容器 div,但这没什么大不了的。

在 React 16.2 中,我们可以这样做以避免周围的容器 div:

render() {
  return (
    <Fragment>
      Some text.
      <h2>A heading</h2>
      More text.
      <h2>Another heading</h2>
      Even more text.
    </Fragment>
  );
}

在任何一种情况下,我们仍然需要一个容器元素包围内部元素。

我的问题是,为什么使用Fragment首选?它对性能有帮助吗?如果是这样,为什么?会喜欢一些见解。

6个回答
  1. 它稍微快一点,内存使用更少(不需要创建额外的 DOM 节点)。这仅对非常大和/或深的树有真正的好处,但应用程序性能通常会因一千次切割而死亡。这少了一刀。
  2. 一些CSS机制比如Flexbox和CSS Grid有特殊的父子关系,div在中间添加s使得在抽取逻辑组件的同时很难保持想要的布局。
  3. DOM 检查器不那么杂乱。:-)

您可以在此 React 问题中找到其他一些用例的描述:添加片段 API 以允许从渲染返回多个组件

@binchik 试过import {Fragment} from 'react'吗?这是一个命名导出。
2021-05-23 15:46:19
那是什么意思“应用程序性能通常会因一千次削减而死亡”。这少了一个切口。你能不能详细说明一下。一般来说,如果我们不想在 UI 中渲染任何内容,我们可以返回 null,我们可以返回 <React.Fragment />,这是更可取/更好的方式。@丹·阿布拉莫夫
2021-05-29 15:46:19
对于number 2,表格实际上是我们最大的问题。所需的结构table>tr>td(可能与thead和相似)为一些笨拙的 React 代码而设计。
2021-06-03 15:46:19
4. 编写定义列表<dt><dd>变得容易多了。之前返回成对元素很尴尬Fragments
2021-06-07 15:46:19
第3点最重要!
2021-06-11 15:46:19

除了上面的所有答案之外,还有一个优点:代码可读性Fragment组件支持语法糖形式,<>. 因此,您问题中的代码可以更轻松地编写为:

render() {
  return (
    <>
      Some text.
      <h2>A heading</h2>
      More text.
      <h2>Another heading</h2>
      Even more text.
    </>
  );
}

根据文档

在 React 中,这会为一个<React.Fragment/>元素脱糖,如上一节中的示例所示。(使用 JSX 的非 React 框架可能会编译成不同的东西。)

一尘不染,对吧?

请注意,<Fragment>如果您需要提供key给片段,您仍然需要使用语法

受不了这块语法糖,看起来是无意的,并没有传达什么内在含义。更喜欢<Fragment>
2021-05-22 15:46:19
@codingsplash CRA 2.0 现在有了。
2021-05-23 15:46:19
@ESR 我个人喜欢它。这么想吧。孩子们什么都没有包裹,就像<>中什么都没有。无形的。
2021-05-28 15:46:19
create-react-app 目前尚不支持这种较短的语法。参考:reactjs.org/docs/fragments.html#short-syntax
2021-06-07 15:46:19
  • 添加了 JSX 以前无法实现的功能
  • 更好的语义 jsx 标记。包装元素在需要时使用,而不是因为它们被迫使用。
  • 减少整体 dom 标记(提高渲染性能和减少内存开销)

它就像当您不需要包装元素时一样简单,您不会被迫使用一个。元素越少越好,但我认为最大的好处是能够在 jsx 中呈现以前不可能的元素,并为包装元素添加更好的语义,因为它们现在是可选的。

这在以前是不可能的:

 <select>
    {this.renderOptions()}
 </select>

看一下 React 15 中的以下内容,您无法判断是否需要包装器元素:

<span>
  <h1>Hello</h1>
  {this.getContent()}
</span>

根据 reactjs.org文档,最重要的需求<Fragment> </Fragment>而不是 div 是避免破坏 HTML 语义。当我们使用 div 而不是<Fragment> </Fragment>我们打破了 HTML 语义。

了解更多关于 html 语义的信息。单击 ,并且在某些情况下,如果您使用 div 而不是 Fragments,它将是无效的 html,例如查看此代码:

class Columns extends React.Component {
  render() {
    return (
      <div>
        <td>Hello</td>
        <td>World</td>
      </div>
    );
  }
}

<table>
      <tr>
        <div>
          <td>Hello</td>
          <td>World</td>
        </div>
      </tr>
 </table>

片段解决了这个问题。

  1. 使用<React.Fragment>...</React.Fragment>,我们可以向 JSX 元素添加父标签,而无需向 DOM 添加额外的节点。
  2. 你可以用 React.Fragment 替换额外的 div 标签
  3. 每次写 React.Fragment 对你来说太长了。React.Fragment 有一个你可以使用的速记语法。它是<>...</>.