“刚学 React,JSX 报错了,说必须返回一个元素,我套了 div,又觉得丑得很。后面发现 <></> 能解决!这到底是啥啊?是 Bug 吗?是魔法吗?是我打开方式不对?”
—— 一个迷茫的前端小白如是说

你好,我是一个正努力摆脱“小白”称号的前端初学者👨‍💻,在学习 React 的时候,我被 <></> 这串神秘符号迷住了。它不像标签,它也不像函数,却能解决好多问题。于是我深挖了一番,发现它的真身是——Fragment

今天,就带你一起揭开它的面纱。🕵️‍♂️


🍿 一、什么是 Fragment?

如果你写过下面这样的 JSX:


jsx

体验AI代码助手

代码解读

复制代码

function App() { return ( <div> <h1>Hello</h1> <p>World</p> </div> ); }

你已经见识过 React 的 “只能返回一个根节点” 规则。为了让它合法,我们经常套个没用的 <div>,像是个“打包盒”。

但是你有没有想过,这个多余的 div:

  • 污染 DOM 结构
  • 影响 CSS 布局
  • 可能让你的结构 语义变差
  • 浪费性能

所以——React 给了我们一个“隐形的 div”:Fragment


🧙‍♂️ 二、Fragment 的两种写法

✨ 1. 标准写法(全名形式)


jsx

体验AI代码助手

代码解读

复制代码

import React from 'react'; function App() { return ( <React.Fragment> <h1>Hello</h1> <p>World</p> </React.Fragment> ); }

这和 div 看起来没什么区别,但神奇的是:它不会出现在最终的 DOM 中!

✨ 2. 简写形式(就是你看到的 <>...</>


jsx

体验AI代码助手

代码解读

复制代码

function App() { return ( <> <h1>Hello</h1> <p>World</p> </> ); }

是的,这一对看起来像 Bug 的符号,其实是 React 的特性,它的名字是:Fragment 简写语法

❗注意点:

  • <>...</> 不能加属性(比如 key、className 都不行)
  • 如果你需要加 key,比如在 .map() 中使用,请老老实实用标准写法:<React.Fragment key={...}>

🎯 三、Fragment 的实战使用场景

✅ 多元素返回的组件


jsx

体验AI代码助手

代码解读

复制代码

function Info() { return ( <> <h2>姓名:阿强</h2> <h3>爱好:Coding</h3> </> ); }

不需要多余的 div,就能让你代码更干净、更语义化!


✅ 列表渲染中的组合结构


jsx

体验AI代码助手

代码解读

复制代码

const list = ['吃饭', '睡觉', '打代码']; function TodoList() { return ( <ul> {list.map((item, index) => ( <React.Fragment key={index}> <li>任务:{item}</li> <li>状态:待完成</li> </React.Fragment> ))} </ul> ); }

你想返回两个 <li>,但 <ul> 下不能直接 return 数组,于是用 Fragment 包起来,完美!


⚙️ 四、和原生 DOM 的联动理解:文档碎片(DocumentFragment)

在你理解 React Fragment 的时候,知道一点原生 DOM 的“碎片化渲染优化”是非常加分的,来看下面这段常见的 DOM 性能优化代码:


js

体验AI代码助手

代码解读

复制代码

const container = document.getElementById('list'); const fragment = document.createDocumentFragment(); // 创建文档碎片 items.forEach(item => { const wrapper = document.createElement('div'); const title = document.createElement('h3'); const desc = document.createElement('p'); title.textContent = item.title; desc.textContent = item.content; wrapper.appendChild(title); wrapper.appendChild(desc); fragment.appendChild(wrapper); // 所有操作都在内存中 }); container.appendChild(fragment); // 一次性挂载,提升性能

🎓 对应知识点解析:

概念 说明
DocumentFragment 是 DOM 的一个轻量“离线节点容器”,用来暂存一堆 DOM,不影响页面渲染
createElement() 创建真实 DOM 元素
textContent 安全设置文本,避免 innerHTML 带来的 XSS 问题
性能优化原理 避免频繁操作 DOM,只在最后统一插入,减少重排(Reflow)和重绘(Repaint)

你可以把 Fragment 理解成 React 层的 DocumentFragment用来包裹多个节点、但不渲染额外结构


🧠 五、Fragment 和 div 的区别总结

对比项 div Fragment(<>...</>
渲染到 DOM ✅ 会渲染 ❌ 不会渲染
是否增加嵌套层 ✅ 会 ❌ 不会
可否添加属性 ✅ 可以 ❌ 简写不行,标准才行
是否语义清晰 ❌ 容易多余 ✅ 更干净语义好
性能表现 😅 多一个节点 💪 更轻量更快

🔚 总结一波

🎁 一句话总结 Fragment:

<>...</> 是 React.Fragment 的简写,是 React 中“无标签的打包工具”,可以让你同时返回多个 JSX 元素,又不多加一层 div,让结构更优雅,性能更高效!

🧩 延伸知识:

React Fragment 的思想和原生 DOM 中的 DocumentFragment 如出一辙:将多个节点先在“幕后”构建好,再一次性“上台”渲染。

两者都体现了“批量操作、集中更新”的性能优化思路,是构建高性能页面的通用手法。


🤝 最后的彩蛋

如果你觉得 Fragment 就只是“省个 div”,那你就低估它了。它是真正让组件组合更自然、结构更语义、性能更优雅的小工具人。


如果你喜欢这样的解析风格,别忘了点赞、收藏、评论三连!
想要继续深入 React 的性能优化、JSX 原理、Hooks 源码解析,欢迎催更!🚀

原文:https://juejin.cn/post/7527216638103240714

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐