由Danny Guo✏️撰写
使用React渲染用户界面的优点之一是很容易将UI分解为组件。但是,一个常见的问题是当我们想返回没有父元素的兄弟元素时。React具有称为Fragments的功能,可以提供解决方案。
问题
如果您不熟悉此问题,请考虑以下示例。
function FAQ() {
return (
<p>Q. What is React?</p>
<p>A. A JavaScript library for building user interfaces</p>
<p>Q. How do I render sibling elements?</p>
<p>A. Use Fragments</p>
);
}
此代码导致错误: Adjacent JSX elements must be wrapped in an enclosing tag.
解决方案
一种选择是用父元素包装这些元素。
function FAQ() {
return (
<div>
<p>Q. What is React?</p>
<p>A. A JavaScript library for building user interfaces</p>
<p>Q. How do I render sibling elements?</p>
<p>A. Use Fragments</p>
</div>
);
}
但是这种方法在DOM中引入了一个无关的元素,从而增加了我们实际上不需要的嵌套级别。
React v16.0引入了另一个选项,即返回一个元素数组。
function FAQ() {
return [
<p>Q. What is React?</p>,
<p>A. A JavaScript library for building user interfaces</p>,
<p>Q. How do I render sibling elements?</p>,
<p>A. Use Fragments</p>
];
}
现在我们需要在元素之间添加逗号。更重要的是,此代码产生了一个关键警告:Warning: Each child in a list should have a unique "key" prop.
向每个元素添加一个关键可解决此问题,但相当麻烦。
function FAQ() {
return [
<p key="q1">Q. What is React?</p>,
<p key="a1">A. A JavaScript library for building user interfaces</p>,
<p key="q2">Q. How do I render sibling elements?</p>,
<p key="a2">A. Use Fragments</p>
];
}
React v16.2给了我们一个更清洁的解决方案,那就是使用Fragments。
function FAQ() {
return (
<React.Fragment>
<p>Q. What is React?</p>
<p>A. A JavaScript library for building user interfaces</p>
<p>Q. How do I render sibling elements?</p>
<p>A. Use Fragments</p>
</React.Fragment>
);
}
我们不再需要提供键,我们不需要添加数组逗号,并且我们仍然避免添加多余的DOM元素,因为React.Fragment
在渲染过程中它不会成为实际的元素。
我们可以导入Fragment
以避免完全写出React.Fragment
。
import React, {Fragment} from "react";
function FAQ() {
return (
<Fragment>
<p>Q. What is React?</p>
<p>A. A JavaScript library for building user interfaces</p>
<p>Q. How do I render sibling elements?</p>
<p>A. Use Fragments</p>
</Fragment>
);
}
但是,一种更好的方法是对Fragments使用简写语法,它看起来像空标记:<>
和</>
。
function FAQ() {
return (
<>
<p>Q. What is React?</p>
<p>A. A JavaScript library for building user interfaces</p>
<p>Q. How do I render sibling elements?</p>
<p>A. Use Fragments</p>
</>
);
}
这给我们和使用一样的好处React.Fragment
,但是我们不需要导入其他任何东西,并且我们的代码看起来更简洁。
速记语法目前不支持的唯一功能是添加一个key
。例如,如果要创建描述列表,则可能会出现问题。在这种情况下,请使用标准语法。
function Dictionary(props) {
return (
<dl>
{props.terms.map(({word, definition}) =>
<React.Fragment key={word}>
<dt>{word}</dt>
<dd>{definition}</dd>
</React.Fragment>
)}
</dl>
);
}
我们需要提供一把钥匙,以避免出现钥匙警告。
但是,在大多数情况下,速记方法是解决我们最初返回同级元素的问题的最佳解决方案。该解决方案效果很好,以至于Vue 在发布v3时也将原生支持Fragments的概念。
使用片段
在过去的两年中,JavaScript生态系统增加了对Fragments的广泛支持。
- React在版本16.2.0(2017年11月28日)中添加了对速记语法的支持
- TypeScript在版本2.6.2中添加了支持(2017年11月27日)
- Babel在版本7中添加了支持(2018年8月27日)
- 更漂亮的版本1.9中添加了支持(2017年12月5日)
- eslint-插件-REACT加入JSX片段排除在7.12.0版(2018年12月28日)使用标准的或速记语法来执行
如果升级依赖项,则可能无需任何其他配置即可使用Fragments。
编者注:这篇文章有什么问题吗?您可以在此处找到正确的版本。
插件:LogRocket,用于Web应用程序的DVR
LogRocket是一个前端日志记录工具,可让您像在您自己的浏览器中一样重播问题。LogRocket无需猜测错误发生的原因,也不要求用户提供屏幕截图和日志转储,而是让您重播会话以快速了解出了什么问题。无论框架如何,它都能与任何应用完美配合,并具有用于记录来自Redux,Vuex和@ ngrx / store的其他上下文的插件。
除了记录Redux动作和状态外,LogRocket还记录控制台日志,JavaScript错误,堆栈跟踪,带有标头+正文,浏览器元数据和自定义日志的网络请求/响应。它还使用DOM来记录页面上的HTML和CSS,甚至可以为最复杂的单页面应用程序重新创建像素完美的视频。
免费试用。
在React中使用Fragment渲染兄弟元素的文章首先出现在LogRocket博客上。