超级面板
文章目录
最新文章
最近更新
文章分类
标签列表
文章归档

React - Fragment

问题描述

在 React16 以前的版本,组件渲染的返回值必须为一个子元素,而不允许是一个子元素的列表,我们经常需要为其包括一层 div 或者 span 等:

// 对于:
Some text.
<h2>A heading</h2>
More text.
<h2>Another heading</h2>
Even more text.

// React 16 以前需要包裹一层额外的 div
render() {
return (
<div>
Some text.
<h2>A heading</h2>
More text.
<h2>Another heading</h2>
Even more text.
</div>
)
}

返回数组

为了解决这样大部分无意义的 DOM 包装,React16.0 提供了返回数组的支持,允许我们返回一个数组:

// React 16.0 以后可以返回数组
render() {
return [
"Some text.",
<h2 key="heading-1">A heading</h2>,
"More text.",
<h2 key="heading-2">Another heading</h2>,
"Even more text."
];
}

但是返回数组也很麻烦,比如,我们需要把文本用引号括起来、需要在每一行末尾加上逗号,而且数组元素还会报出没有 key 的错误,有需要为每一个元素指定 key 属性,这样一点也不好用,反而需要修改更多内容。

Fragment

为了彻底解决这个问题,React16.2 重新引入了 React.Fragment 标签,专门用于解决这个问题:

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

乍一看,这个和之前使用 div 包装的方式很相似,但是 Fragment 并不会真的在外面包装一层,看下面的例子:

render() {
return (
<table>
<tr>
<Columns />
</tr>
</table>
);
}

// 自己包装,需要多注意应用场合,不然可能包装出来错误的结构:
const Columns = () => (
<div>
<td>Hello</td>
<td>World</td>
</div>
);

// 结果,结构明显错误
<table>
<tr>
<div>
<td>Hello</td>
<td>World</td>
</div>
</tr>
</table>

// 使用 Fragment
return (
<React.Fragment>
<td>Hello</td>
<td>World</td>
</React.Fragment>
);

// 结果,结构正确,也没有额外的无意义的结点出现
<table>
<tr>
<td>Hello</td>
<td>World</td>
</tr>
</table>

缩写标签 <></>

由于这个会比较常用,又引入了简写的标签: <></>:

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

注意:目前版本,React.Fragment 只能接受 key 这一个属性,未来版本可能做出改进:

key is the only attribute that can be passed to Fragment. In the future, we may add support for additional attributes, such as event handlers.

而简写的 <></> 标签并不能接收任何属性,同时可能一些工具不支持。

参考

本文主要参考了 React 的官方文档: Fragments