『React』Fragment的用法及简写形式

在 React 渲染组件时,每个组件只能返回一个根节点(root element)。传统上,如果我们需要渲染多条并列的元素,通常会使用一个多余的 <div> 或者其他容器标签将它们包裹起来。但是,这样会在最终的 HTML 中多生成一个无意义的节点,可能会影响样式、布局,甚至带来不必要的性能开销。

为了消除这种"无意义的包裹元素",React 引入了 <Fragment> 组件。它 在渲染时不会生成额外的 DOM 节点,仅仅是一个"虚拟"容器,帮助我们在 JSX 中满足"只能返回一个根节点"的规则。它的本质只是 React 的一个内置组件,本身并不在 DOM 中出现。

Fragment 的用法

最直接的写法是直接从 React 库中导入 Fragment,然后在 JSX 中如下使用:

jsx 复制代码
import React, { Fragment } from 'react';

function MyComponent() {
  return (
    <Fragment>
      <h1>标题</h1>
      <p>文字描述</p>
    </Fragment>
  );
}

上面代码,组件返回了一个 <Fragment>,内部包含多个并列元素;渲染到网页时并不会多出一个父级标签,而是直接渲染 <h1>、<p>、<ul> 三个元素。

如果你不想写 import { Fragment } from 'react',也可以直接使用全称:

jsx 复制代码
import React from 'react';

function MyComponent() {
  return (
    <React.Fragment>
      <h1>标题</h1>
      <p>这是一段描述文字。</p>
    </React.Fragment>
  );
}

export default MyComponent;

两者效果是完全一样的。

简写方式

从 React 16.2 开始,官方支持了 <Fragment> 的简写语法------空标签 <>...</>,使用起来更简洁:

jsx 复制代码
function MyComponent() {
  return (
    <>
      <h1>标题</h1>
      <p>这是一段描述文字。</p>
      <ul>
        <li>列表项 1</li>
        <li>列表项 2</li>
      </ul>
    </>
  );
}

两者(<Fragment>...</Fragment> 与 <>...</>)在渲染结果上没有区别。它们都不会在 DOM 中生成额外的节点。

注意: 空标签的简写语法 不能 使用 key 或其他属性,比如 <> 无法写成 < key="..." >。如果需要给 Fragment 本身指定 key,就必须使用完整写法 <Fragment key={...}>...</Fragment>。

比如这种情况

jsx 复制代码
import React from 'react';

function TodoList({ todos }) {
  return (
    <ul>
      {todos.map((todo) => (
        <Fragment key={todo.id}>
          <li>{todo.text}</li>
          <li>状态:{todo.completed ? '已完成' : '未完成'}</li>
        </Fragment>
      ))}
    </ul>
  );
}

如果使用简写空标签 <>...</> 则无法指定 key,会导致警告或无法正常做列表 Diff。因此在需要绑定 key 的场景下一定要使用 <Fragment key={...}>...</Fragment>。

常见使用场景

组件返回多个并列节点

如果父级容器已足够,只想返回多条标签而不加冗余容器:

jsx 复制代码
function ArticleSummary({ title, excerpt }) {
  return (
    <>
      <h2>{title}</h2>
      <p>{excerpt}</p>
    </>
  );
}

表格中渲染多行

<table> 要求直接返回 <tr>,不能多包一层 <div>。<Fragment> 可把两行或多行当作一组处理:

jsx 复制代码
import React, { Fragment } from 'react';

function DataTable({ list }) {
  return (
    <table>
      <tbody>
        {list.map(item => (
          <Fragment key={item.id}>
            <tr>
              <td>{item.name}</td>
              <td>{item.value}</td>
            </tr>
            <tr>
              <td colSpan="2">详情:{item.detail}</td>
            </tr>
          </Fragment>
        ))}
      </tbody>
    </table>
  );
}

条件渲染多节点

当一个条件下需要返回多条并列节点,用 Fragment 代替冗余父元素,更清爽:

jsx 复制代码
function UserStatus({ user }) {
  return (
    <>
      <h3>{user.name}</h3>
      {user.online ? <p>在线</p> : <p>离线</p>}
    </>
  );
}

与其他方式对比

多包一个 <div>

虽然能满足语法,但会产生额外节点,可能破坏 CSS 布局(如 Flex、Grid)或增深 DOM 层级。

返回数组

可以直接写数组返回多个元素,但每个元素都要写 key,可读性差:

jsx 复制代码
function Example() {
  return [
    <h1 key="title">标题</h1>,
    <p key="content">内容</p>,
  ];
}

相比之下,Fragment 更简洁可读,且不用给内部每个元素都写 key(只需给 Fragment 本身写一次)。


以上就是本文的全部内容了,如果本文对你有帮助的话请转发给你的工友~

想了解 React 的更多玩法,欢迎关注《React 中文教程》

相关推荐
只睡四小时5 小时前
AI 生成 PPTX:11 页课件编译出 429 个形状
javascript·python·pptx·ai生成ppt·ooxml
deli0076 小时前
连接池到底配多大?QPS 和 RT 算一遍,再跑 1 万次请求实测超时率
前端
风花一世月6 小时前
🏮 我把三坊七巷做成了能飞的 3D 地图(901 个真实建筑轮廓、20 处景点,在线直接玩)
前端
特立独行的猫A6 小时前
用仓颉语言写一个串口调试助手:cj-tauri 实战
前端
小凯在掘金6 小时前
Shadow DOM 和 Virtual DOM ?别再傻傻分不清
前端·html
郑州光合科技余经理6 小时前
本地生活平台搭建:跨业态用户标识怎么贯通
java·开发语言·前端·后端·uni-app·php·ai编程
shmily麻瓜小菜鸡6 小时前
Axios 中 params 与 data 的区别与原理
javascript·typescript
数据掘金6 小时前
埋点事件命名升级时老数据怎么办
前端
对空六课6 小时前
Vue 组件曝光埋点为什么会重复触发?去重方案与实现思路
服务器·前端·算法·数据分析
isha6 小时前
Univer拆解——从类与方法的视角分析
前端·javascript