- 教程
- 知识库
【免费下载链接】tech-interview-for-developer
👶🏻 신입 개발자 전공 지식 & 기술 면접 백과사전 📖
本指南聚焦 React 的
Fragment语法:当 JSX 规则要求组件return只能返回单个根元素时,Fragment提供了一种「只分组、不生成 DOM 节点」的解决方案。文章以 Table 组件中嵌套td的真实场景为主线,完整覆盖显式<Fragment>、简写<>、带 key 的列表渲染与布局场景,帮助你彻底掌握这一高频 React 面试与实战知识点。
一、背景:JSX 的单一根元素规则
在 React 中,JSX 最终会被编译成React.createElement(...)调用。由于一次createElement调用只能接收一个「元素类型」作为首参,因此一个组件return语句中必须且只能返回一个根节点——这正是 JSX 文件中「return 时要用一个标签把所有内容包起来」这一规则的由来。
面对「多个兄弟节点需要同时返回」的需求,新手最常见的做法是套一层<div>。绝大多数情况下这没有问题,但在某些场景下,多余的<div>会直接破坏页面结构甚至造成渲染异常。此时就需要Fragment登场:它允许你将一组 JSX 元素分组,而不会在 DOM 树中产生任何额外的节点。
二、问题复现:Table 组件中多余的<div>破坏表格结构
假设存在一个Table组件,它通过<Columns />子组件来渲染表格的列单元格:
import { Component } from 'react' import Columns from '../Components' class Table extends Component { render() { return ( <table> <tr> <Columns /> </tr> </table> ); } }Columns组件需要返回多个<td>元素。由于 JSX 规则要求return只能返回单个根元素,于是开发者习惯性地用<div>把它们包起来:
import { Component } from 'react' class Columns extends Component { render() { return ( <div> <td>Hello</td> <td>World</td> </div> ); } }注意:原文档中导入语句写作from 'React',实际工程中应从'react'(小写)导入。上面代码已按正确写法呈现。
此时查看最终渲染出的 DOM 树,会发现结构变成了:
<table> <tr> <div> <td>Hello</td> <td>World</td> </div> </tr> </table><table>的直接子元素必须是<thead>、<tbody>、<tr>等合法标签,而这里<tr>内部出现了一个<div>,这既不符合 HTML 规范,也会让浏览器在解析表格时出现异常行为。根因就是Columns组件用<div>强行包裹了<td>兄弟节点。
三、解决方案:使用<Fragment>显式分组
把Columns组件中的<div>替换为<Fragment>,问题即可解决:
import { Component, Fragment } from 'react' class Columns extends Component { render() { return ( <Fragment> <td>Hello</td> <td>World</td> </Fragment> ); } }Fragment的关键特性是:它只承担 JSX 层面上的「分组」职责,渲染时不会在 DOM 树中生成任何节点。因此最终 DOM 树变为:
<table> <tr> <td>Hello</td> <td>World</td> </tr> </table>表格结构恢复合法,两个<td>直接成为<tr>的子节点,渲染恢复正常。
补充说明:
<Fragment>既可用于类组件(如上面示例),也可用于函数式组件,规则一致。它等价于只输出子元素、自身不产生包裹节点的「透明容器」。
四、更简洁的写法:<>...</>简写语法
如果不需要给 Fragment 传任何属性(例如key),可以直接使用空标签简写形式:
import { Component } from 'react' class Columns extends Component { render() { return ( <> <td>Hello</td> <td>World</td> </> ); } }<>与</>之间不书写任何标识符,语义与<Fragment>完全一致,且同样不会在 DOM 中生成额外节点。由于无需导入Fragment,它在日常开发中使用频率更高,也是编写无多余嵌套 JSX 的首选方式。
两种写法的差异仅在于:<>无法携带任何属性(如key);当需要给分组后的元素设置key(典型场景是列表渲染)时,必须使用显式的<Fragment key={...}>写法。
五、为什么要避免多余的<div>:布局与渲染层面的双重考量
原文档特别指出:在父子关系的元素之间使用 flex、grid 布局时,多余的<div>会破坏样式结构。
具体来说:
- flex/grid 布局依赖直接的父子层级:
display: flex或display: grid的容器只会对其「直接子元素」应用布局规则。若在布局容器与其真实内容之间插入一层<div>,布局算法的直接子级就变成了这个<div>,原本期望参与排版的元素(如表格单元格、列表项)会脱离布局上下文,导致间距、对齐、换行全部错乱。 - 额外节点带来样式与选择器的负担:多余的
<div>会增加 CSS 选择器匹配的复杂度,也可能无意间触发全局样式(如通用div选择器),造成难以排查的样式污染。 - 影响 DOM 体积与渲染性能:虽然单个
<div>的开销很小,但在大型列表场景(如渲染成百上千行)中,每一行都多一层包裹节点,累积起来的 DOM 节点数、内存占用与首屏解析成本都会被放大。Fragment不产生节点,天然规避了这部分开销。
因此,当需要同时返回多个兄弟节点、且不希望引入额外包裹层时,Fragment是正确选择。
六、进阶用法:key 属性与列表渲染
除简单分组外,Fragment还有一个高频进阶场景——在列表循环中给一组元素添加key。
当你在map循环里返回多个并列节点,又不想用<div>包裹时,可以用显式Fragment携带key:
import { Fragment } from 'react' function Glossary({ items }) { return ( <dl> {items.map(item => ( <Fragment key={item.id}> <dt>{item.term}</dt> <dd>{item.description}</dd> </Fragment> ))} </dl> ); }<dt>与<dd>是一对不可拆分的兄弟节点,但它们需要分别作为<dl>的直接子元素;这里用<Fragment key={item.id}>分组既满足了「单根元素」的 JSX 规则,又保证了列表项的key唯一性,同时不产生任何多余 DOM 节点。这一写法在面试中常作为「Fragment 与 key 结合使用」的考察点。
注意:
<>简写形式不支持key属性,此类场景必须使用<Fragment key={...}>。
七、本项目中的延伸阅读与面试要点
在 tech-interview-for-developer 仓库中,React 专题位于 Web/React 目录,与本文同级的还有以下文档可串联学习:
- React Hook:讲解
useState、useEffect等 Hook 机制,与本文同属 React 组件编写规范的基础知识; - React & Spring Boot 연동하여 환경 구축하기:展示 React 组件化开发在实际前后端项目中的落地方案。
围绕本文知识点,面试中常被追问的要点可归纳为:
- 为什么 JSX 的 return 必须返回单根元素?——JSX 编译为
React.createElement调用,一次调用只能接收一个元素类型作为首参,多个并列根节点无法编译。 - Fragment 与 div 的本质区别?——
Fragment不渲染任何 DOM 节点,仅做分组;div会真实插入 DOM。 - Fragment 的两种写法及适用场景?——
<Fragment>(可带key)与<>(不可带属性),列表渲染需要key时用前者。 - 什么时候必须用 Fragment?——table 内嵌
td、flex/grid 直接子元素、dl内的dt/dd组合等对 DOM 层级敏感的场景。
八、总结
Fragment是 React 中「轻量分组」的标准方案:它遵守 JSX 单根元素规则,又不在 DOM 中留下痕迹。掌握它的核心价值在于对 DOM 结构保持敏感——当遇到表格、列表、flex/grid 布局被多余标签破坏的问题时,优先想到用<Fragment>或<>替代<div>。这既是实际开发中排查样式与结构异常的高频手段,也是 React 面试中考察 JSX 原理与组件设计能力的基础考点。
- 教程
- 知识库
【免费下载链接】tech-interview-for-developer
👶🏻 신입 개발자 전공 지식 & 기술 면접 백과사전 📖
相关推荐
React Bits 之 React Fragments:让组件返回多个子元素而不污染 DOM
React Bits 之 React Fragments:让组件返回多个子元素而不污染 DOM 导读 在 React 中,组件的 render 方法通常只能返回
前端教程SQL 与 NoSQL 数据库选型全解析:tech-interview-for-developer 面试知识点精讲
SQL 与 NoSQL 数据库选型全解析:tech interview for developer 面试知识点精讲 导读 在开发 Web 应用时,数据库选型是每
教程知识库tech-interview-for-developer 网络面试知识点:Blocking I/O 与 Non-Blocking I/O 原理深度解析
tech interview for developer 网络面试知识点:Blocking I/O 与 Non Blocking I/O 原理深度解析 导读 本
教程知识库
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考