一文让你彻底理解 React Fragment
对于 React 开发人员来说,从一个组件返回多个元素一直是个问题。这是因为 React 依赖于创建用于协调的树形结构。因此,当在呈现方法中返回多个元素时,用于协调的算法将不会像预期的那样发挥作用,树将有一个组件的根节点的假设将不再有效。React Fragment 在库的 16.2 版本中修复了这个问题。
1. 什么是 React Fragments?
React Fragment 是 React 中的一个特性,它允许你对一组子元素进行分组,而无需向 DOM 添加额外的节点,从而允许你从 React 组件中返回多个元素。
要从 React 组件返回多个元素,需要将元素封装在根元素中。这种方法效率不高,在某些情况下可能会引起问题。如:
代码语言:javascript复制function TableData () {
return (
<div>
<td>Eat</td>
<td>Learn</td>
<td>Code</td>
</div>
);
}
function Table () {
return (
<table>
<tr>
<TableData />
</tr>
</table>
);
}
上面的代码将生成下面的 HTML 。
代码语言:javascript复制<table>
<tr>
<div>
<td>Eat</td>
<td>Learn</td>
<td>Code</td>
</div>
</tr>
</table>
因此,正如你所看到的,在 div
元素中包装 <td>
标签打破了表的父子关系。为了按照预期工作,<td>
标签必须单独呈现,而不将它们包装在 div
元素中。在这种情况下,最好使用 React Fragment。
2. React Fragment 对比 div 元素
在 React 中,Fragment
和 div
可以互换使用。两者之间的主要区别是 Fragment
从 DOM 树中清除所有额外的 div
,而 div
向 DOM 树中添加一个 div
。
使用 React Fragments,我们可以创建更清晰、更容易阅读的代码。它渲染组件更快,使用的内存更少。每个元素都按预期呈现。而 div
会扩展 DOM,因为当你的网站上有太多的 HTML 标签时,会出现长嵌套节点。
div
元素有更多的方法和属性,这导致它消耗更多的内存,从而使页面加载时间变慢;原型链像 HTMLDivElement -> HTMLElement -> Element -> Node -> EventTarget
,而 React Fragments 有较少的方法与原型链DocumentFragment -> Node -> EventTarget
。
使用 Fragment
,你可以重用应用程序的部分内容。然而,在有些情况下,必须得使用 div
而不是 Fragment
。
例如,使用 Fragment
不允许你设计组件,因为你必须将目标元素包装在 div
中。此外,如果你要向组件的元素添加 key
,则必须使用 div
。根据这一点,你可以根据你希望 React 应用程序完成的任务,交替使用这两种方法。
3. 使用 div 出现的问题
让我们详细看看使用 div
时的一些问题。
div
元素展开 HTML DOM,导致浏览器消耗比预期更多的资源。- 当 DOM 太大时,它会消耗大量内存,导致页面在浏览器中加载缓慢。
- 随着 DOM 变得越来越大、越来越嵌套,调试和跟踪额外节点的来源变得越来越困难。
- 使用
div
来呈现组件可能会阻塞 HTML 导致性能问题。
4. Fragment 的优势
React Fragment 对比可能导致无效 HTML 的问题的<div>
元素有以下优点。
- React Fragment 的代码可读性更高。
- 因为React Fragment 有一个更小的DOM,它们渲染更快,使用更少的内存。
- React Fragment 允许按预期呈现 React 组件,而不会引起任何父子关系问题。
- Fragment 允许返回多个 JSX 元素,这解决了 react 应用程序中由每个组件只能返回一个元素的约束引起的无效 HTML标记的问题。
5. 在 React Fragment 中使用 key prop
在某些情况下,React 应用程序中需要 key prop。在 react 中,key prop 通常用于控制组件实例。React 在这样的场景中使用 key prop 来识别哪些项发生了更改、删除或添加。在带有 Fragment 的 React 应用程序中使用 key prop 将类似于下面的代码片段。
代码语言:javascript复制function TableData () {
return (
{data.map(rec=>
<React.Fragment key={rec.id}>
<td>{rec.hobby}</td>
</React.Fragment>
)}
);
}
6. 使用简写
除了使用 React Fragment, React 还提供了一个简写符号 <></>
将多个元素封装在一起,其工作原理与 React Fragment 类似,但内存负载更低。在 react 应用程序中,简写符号 <></>
实现如下。
<function TableData () {
return (
<>
<td>Eat</td>
<td>Learn</td>
<td>Code</td>
<>
);
}
上面的代码将生成预期的 HTML。
代码语言:javascript复制<table>
<tr>
<div>
<td>Eat</td>
<td>Learn</td>
<td>Code</td>
</div>
</tr>
</table>
然而,这种方法有一些缺点。例如,不能实现 key prop
,因为简写符号 <></>
在这里不起作用。毕竟,它不能接受一个属性。
7. Fragment 的使用
现在让我们看看如何在 React 应用程序中使用 Fragment。在下面的例子中,我们将使用 React Fragment 来呈现一个表中的项目列表。
代码语言:javascript复制import "./App.css";
import React from "react";
const Table = ({ children, style }) => {
return <div>{children}</div>;
};
const TableData = () => {
return (
<React.Fragment>
<td>John Doe</td>
<td>16</td>
<td>Developer</td>;
</React.Fragment>
);
}
function App() {
return (
<Table>
<tr>
<th>Name</th>
<th>Age</th>
<th>Occupation</th>
</tr>
<TableData />
</Table>
);
}
export default App;
在上面的代码片段中,我们创建了两个要在应用程序中呈现的组件。在渲染方法中,我们使用 React Fragment 而不是将 TableData
组件中的元素包装在 div
中,这样,我们的表数据将按预期渲染。
8. 小结
在本文中,你已经了解了 React Fragment。我们首先了解了 React Fragment 是什么,以及什么时候在 React 应用程序中使用它。然后我们进一步演示了如何在实际应用中使用它。