1. 为什么需要Fragment?
在React中,JSX必须返回单个根元素。过去我们常常被迫添加无意义的 <div>
包装器:
jsx
// 旧写法:不必要的div
<div>
<h1>标题</h1>
<p>内容</p>
</div>
这会导致:
- DOM树层级变深
- 样式污染风险
- 不必要的渲染开销
2. Fragment的两种形态
2.1 完整形态
jsx
import { Fragment } from 'react';
function Demo() {
return (
<Fragment>
<h1>Hello</h1>
<p>World</p>
</Fragment>
);
}
2.2 语法糖形态
jsx
function Demo() {
return (
<>
<h1>简洁版</h1>
<p>不需要额外导入</p>
</>
);
}
3. 列表渲染中的关键用法
在遍历列表时,Fragment配合key属性可以避免包裹元素:
jsx
function TodoList({ items }) {
return (
items.map(item => (
<Fragment key={item.id}>
<h3>{item.title}</h3>
<p>{item.content}</p>
</Fragment>
))
);
}
⚠️ 重要规则 :
- 遍历时必须提供key
- key要放在Fragment上而非子元素
4. 性能优化原理
Fragment就像DOM世界的"文档碎片",参考原生JS实现:
js
<script>
// 原生JS优化方案
const fragment = document.createDocumentFragment();
items.forEach(item => {
const el = document.createElement('div');
// ...创建元素
fragment.appendChild(el);
});
container.appendChild(fragment);
</script>
React Fragment实现了类似的批量更新机制,减少重排重绘。
5. 最佳实践
✅ 该用场景:
-
列表项需要多元素但不想包裹div
-
表格结构需要直接渲染
-
高阶组件返回多个元素 ❌ 避免滥用:
-
单个子元素不需要Fragment
-
需要样式容器时应该用div
6. 趣味冷知识
- Fragment在React 16.2版本加入
- 空标签 <></> 内部叫"短语法"
- 某些测试工具可能需要显式导入Fragment 下次当你在组件中想用
时,先问问自己:"这个div真的有必要吗?或许Fragment才是更好的选择!"