当前位置: 首页 > news >正文

React 第二十五节 <Fragment></Fragment> 的用途以及使用注意事项详解

文章如果错误偏差,烦请及时批评指正

一、为什么要使用 <Fragment>

因为在 React 中,组件必须返回单个根元素。当我们尝试直接返回相邻的 JSX 元素时:

    function BrokenComponent() {
        return (
            <h1>标题</h1>
            <p>正文内容</p>
        );
    }
    //  报错:Adjacent JSX elements must be wrapped in an enclosing tag

传统解决方案是使用

包裹,但这会带来 三大问题

1、破坏布局结构:多余的 DOM 节点可能干扰 CSS 布局(如 Flex/Grid)
2、性能损耗:增加无意义的 DOM 层级
3、语义污染:无关的

影响 HTML 语义化

二、基础用法:两种写法全解析

  1. 显式写法(推荐场景:需要 key 属性时)
    当我们遍历数组时,需要添加 key 属性时,我们需要显式的使用
import React, { Fragment } from 'react';
function ListItems() {
  return (
    <Fragment>
      <li>第一项</li>
      <li>第二项</li>
      <li>第三项</li>
    </Fragment>
  );
}
  1. 简写语法(空标签)
    function ShortSyntax() {
    return (
        <>
        <h2>欢迎界面</h2>
        <button>开始使用</button>
        </>
    );
    }

三、实际开发过程中的应用场景

  1. 列表渲染(必须使用 key)
    function UserList({ users }) {
    return users.map(user => (
        <Fragment key={user.id}>
        <dt>{user.name}</dt>
        <dd>{user.email}</dd>
        </Fragment>
    ));
    }
    //  正确:Fragment 支持 key 属性
    //  错误:空标签语法 <></> 不能添加属性
  1. 条件渲染
    function AuthButton({ isLoggedIn }) {
    return (
        <Fragment>
        {isLoggedIn ? (
            <button>退出登录</button>
        ) : (
            <Fragment>
            <button>登录</button>
            <button>注册</button>
            </Fragment>
        )}
        </Fragment>
    );
    }
  1. 表格结构
    需要注意添加 标签的位置
    function TableData() {
    return (
        <table>
            <tbody>
                <tr>
                <Fragment>
                    <td>单元格1</td>
                    <td>单元格2</td>
                </Fragment>
                </tr>
            </tbody>
        </table>
        );
    }
    // 注意:直接包裹 <tr> 会破坏表格结构
  1. 组合组件
    function Layout() {
    return (
        <>
        <Header />
        <MainContent />
        <Footer />
        </>
    );
    }
  1. 高阶组件(HOC)
    const withLogger = (WrappedComponent) => {
        return (props) => (
            <Fragment>
                <ConsoleLogger />
                <WrappedComponent {...props} />
            </Fragment>
        );
    };
  1. 渲染数组
    function ArrayRender() {
    return (
        <>
        {['A', 'B', 'C'].map((item) => (
            <Fragment key={item}>
            <span>{item}</span>
            <br />
            </Fragment>
        ))}
        </>
    );
    }

四、深度原理剖析

源码实现(简化版):

    const Fragment = Symbol.for('react.fragment');

    function createFragment(children) {
    return {
        $$typeof: Symbol.for('react.element'),
        type: Fragment,
        props: { children },
        key: null
    };
    }

React 在调和(Reconciliation)阶段会:
识别 Fragment 类型
直接平铺其子节点
不创建真实 DOM 节点

五、开发者常遇到问题

1、样式丢失陷阱

// 错误示例:
    <div className="parent">
        <>
            <Child style={{ margin: 10 }} />
        </>
    </div>
// 正确:直接在父级设置样式容器 无脑简写导致 key 缺失
// 错误示例:
    {items.map(item => (
    <>  // 错误 缺少 key
        <span>{item.name}</span>
        <span>{item.value}</span>
    </>
    ))}

2、多层 Fragment 嵌套

// 不良实践:
<>
  <>
    <ComponentA />
    <ComponentB />
  </>
  <ComponentC />
</>
// 建议:单层 Fragment 保持结构清晰

3、与第三方库的冲突

    // 某些动画库(如 Framer Motion)需要真实 DOM:
    <motion.div>
        <Fragment> //错误 动画失效
            {/* content */}
        </Fragment>
    </motion.div>

4、开发工具调试困惑
Fragment 在 React DevTools 中显示为 ,可通过设置显示名称优化:

    const MyFragment = ({ children }) => <Fragment>{children}</Fragment>;
    MyFragment.displayName = 'MyFragment'; // 调试更友好

七、注意事项

1、优先使用空标签语法:<>...</> 简洁直观
2、需要 key 时切回显式 Fragment:列表项必须添加
3、避免深度嵌套:超过 3 层应考虑组件拆分,考虑组件的单一性易维护性
4、组件中需要结合 TypeScript 增加类型检查,避免使用人员传入不符合类型的数据

const FragmentWrapper: React.FC<{ children: React.ReactNode }> = 
  ({ children }) => <>{children}</>;

5、性能敏感场景实测:大数据列表优先选择 Fragment
6、最后:当你在纠结是否使用 Fragment 时,先问自己两个问题:
这个容器是否需要任何样式或交互?
添加 DOM 节点是否会影响父级布局?
满足这两个条件,可以放心使用

相关文章:

  • 基于 MATLAB 的粒子滤波算法实现示例,用于处理手机传感器数据并估计电梯运行参数。
  • 回归预测 | Matlab实现PSO-HKELM粒子群算法优化混合核极限学习机多变量回归预测
  • MySQL篇之对MySQL进行参数优化,提高MySQL性能
  • Mac ARM 架构的命令行(终端)中,删除整行的快捷键是:Ctrl + U
  • 基于微信小程序校园订餐的设计与开发(ssm论文源码调试讲解)
  • Nginx之rewrite重写功能
  • 嵌入式硬件篇---原码、补码、反码
  • Java实现MinIO上传PDF文件并配置浏览器在线打开而非下载
  • NHANES指标推荐:DDA!
  • 小爱音箱控制手机和电视听歌的尝试
  • np.hstack函数的用法
  • Vue学习笔记4
  • 文心一言4月起全面免费,6月底开源新模型:AI竞争进入新阶段?
  • uniapp - iconfont下载本地并且运用至项目上
  • 「软件设计模式」单例模式
  • NO.18十六届蓝桥杯备战|循环嵌套|乘法表|斐波那契|质数|水仙花数|(C++)
  • C++ Primer 函数基础
  • 基于Pygame搭建的雷达、光电和数据链数据生成引擎
  • 【进程与线程】如何编写一个守护进程
  • 在Ubuntu24.04上安装Stable-Diffusion1.10.1版本
  • 烟台做网站优化/沈阳seo排名公司
  • 简单的网站开发工具/网站流量排名查询工具
  • 手表网站布局/百度推广登陆网址
  • 网站放在服务器上/51网站统计
  • 西安网站建设哪家公司好/google谷歌搜索
  • 数字作品商城wordpress/在线seo