🔥React新手必学: ’Fragment‘ 如何优化你的 JSX 代码结构🔥

78 阅读4分钟

前言

在 React 开发中,组件经常需要返回多个同级元素。按照 JSX 语法要求,这些元素必须包裹在一个父容器中。传统解决方案是使用 <div> 标签包裹,但这会带来三个实际问题:

  1. 破坏语义结构:在 <table><dl> 等需要特定子元素的场景中,额外的 <div> 会导致 HTML 结构无效。

  2. 影响样式表现:多余的 DOM 节点可能干扰 CSS 布局,特别是在使用 Flex 或 Grid 时。

  3. 降低性能:不必要的 DOM 节点会增加渲染负担和内存占用。

React 16.2 引入的 Fragment 特性提供了专业解决方案。它允许开发者:

  • 分组多个子元素而不产生额外 DOM 节点
  • 保持代码结构清晰
  • 完全遵守 HTML 规范要求

本文将系统解析 Fragment 的工作机制、具体应用场景和最佳实践,帮助开发者写出更专业、更高效的 React 代码。通过对比实验数据和实际案例,我们将验证其在性能优化和代码维护性方面的优势。

Fragment 是什么?

<Fragment>是一个虚拟容器,不会渲染为真实的DOM元素,通常使用 <>...</> 代替,它们都允许你在不添加额外节点的情况下将子元素组合。

比如这样:

function MyComponent() {
  return (
    <>
      <ChildA />
      <ChildB />
      <ChildC />
    </>
  );
}

Fragment 为什么存在?

它的大多用处都是用来包裹子元素使用的,由于React的底层设计,其规定一个组件只能返回一个元素,所以呢为了将组件中的其他子组件集合起来,我们就需要一个父元素来挂载,把它们全部变成一个元素。

就像游戏规定了我们只能拿走一盒子奖品,但是我们就可以把其他盒子的奖品塞到一个盒子里,那也是一盒子奖品,就是这样哒~

就拿上面的例子说,既然我们只需要一个父元素,为什么不直接用<div>呢?

<div>等标签会带来DOM污染问题,我们本意上并不想给这几个<Child />加上一个父元素的,我们希望它就是分散的像兄弟一样的,比如我早在它们挂载的地方用了flex布局,如果加上了<div>等标签,就改变了它们的存在方式,flex布局就直接失效了....再比如呢,它们本来是放在<table>中的,如果我加了个<div>,那不就报错了嘛。。。。

这样,就造成了DOM的污染,react又渲染了多余的没必要的dom元素,对性能也是一种消耗。

其次呢,<Fragment>的存在能更好的让列表渲染和进行数据更新:

{items.map(item => (

<React.Fragment key={item.id}>

<dt>{item.title}</dt>

<dd>{item.desc}</dd>

</React.Fragment>

))}

在这里我们用Fragment标签将一个标题和一个描述包裹在一起,同时添加了唯一的key值,这样在无形中就给它们分了组,让它们更具有条理性,而且由于react的diff算法,给它们每一个加了唯一的key,react能够迅速找到发生位置的元素,从而实现它的更新和渲染。

Fragment 怎么用?

它的语法很简单:

标准语法

<Fragment>
</Fragment>

简易语法

<>
</>

用法:

返回多个元素 

使用 Fragment 或简写语法 <>...</> 将多个元素组合在一起,你可以使用它将多个元素等效于单个元素。例如,一个组件只能返回一个元素,但是可以使用 Fragment 将多个元素组合在一起,并作为一个元素返回:

function Post() {

  return (

    <>

      <PostTitle />

      <PostBody />

    </>

  );

}

分配多个元素给一个变量 

和其他元素一样,你可以将 Fragment 元素分配给变量,作为 props 传递等:

function CloseDialog() {

  const buttons = (

    <>

      <OKButton />

      <CancelButton />

    </>

  );

  return (

    <AlertDialog buttons={buttons}>

      Are you sure you want to leave this page?

    </AlertDialog>

  );

}

组合文本与组件

你可以使用 Fragment 将文本与组件组合在一起:

function DateRangePicker({ start, end }) {

  return (

    <>

      From

      <DatePicker date={start} />

      to

      <DatePicker date={end} />

    </>

  );

}

渲染 Fragment 列表

在这种情况下,你需要显式地表示为 Fragment,而不是使用简写语法 <></>。当你在循环中渲染多个元素时,你需要为每一个元素分配一个 key

function Blog() {

  return posts.map(post =>

    <Fragment key={post.id}>

      <PostTitle title={post.title} />

      <PostBody body={post.body} />

    </Fragment>

  );

}

这也就是上面所提到的,写个key有利于diff算法的查找,提升操作虚拟dom的性能。

总结

在上面的例子中,1,2,3,三种用法,其实都是利用了fragment能够表达语义更清晰,没有副作用,告诉react这俩组件是在一起的从而更好的更新,但是不会影响实际的里面元素的关系,不会影响布局,一举两得!

Fragment 解决了组件返回多元素时的 DOM 污染问题,兼顾语义化和性能,其不会作为真实的dom元素被渲染,这是它的核心价值。