Material-UI Accordion 折叠面板完全指南
【免费下载链接】material-uiMaterial UI: Comprehensive React component library that implements Google's Material Design. Free forever.项目地址: https://gitcode.com/GitHub_Trending/ma/material-ui
Material-UI(MUI)的折叠面板 Accordion 组件,帮你把 FAQ 答案、多层级设置项、长文档目录这类内容收进可点击展开的面板里,减少页面滚动量,信息又不丢失。下面从适用场景讲到受控模式和嵌套写法,带你把它用到顺手。
一、什么时候该用 React 折叠面板 📋
适合"信息多、但用户一次只看一块"的页面,常见有三种:
- FAQ 问答页:十几个问题平铺太长,收进面板后一屏能看完目录感;
- 多层级设置页:如用户管理、过滤规则、个人数据,按类别分组折叠;
- 内容目录或长文档分区:先露出小节标题,点哪看哪。
只要判断标准是"读者需要按需展开",折叠面板比手写下拉脚本省事得多,展开收起、键盘操作都由组件内置。
二、四个核心组件,一张表看懂
折叠面板是"一个容器 + 三块零件"的组合,各管一摊:
| 组件 | 职责 |
|---|---|
Accordion | 面板容器,持有展开/折叠状态,处理点击与键盘交互 |
AccordionSummary | 标题区域,点击它触发展开或收起,展开图标也挂在它上面 |
AccordionDetails | 内容区域,包裹面板正文,可以是文本、表单等任意 React 组件 |
AccordionActions | 可选的底部操作区,用来放"重置""删除"这类按钮 |
四个组件必须成组使用,Accordion里至少放一个Summary和一个Details,顺序不能反。
三、最小示例:30 秒搭好一个折叠面板
最小可运行片段长这样(省略 import):
<Accordion defaultExpanded> <AccordionSummary expandIcon={<ExpandMoreIcon />}> <Typography>面板标题</Typography> </AccordionSummary> <AccordionDetails> <Typography>点击标题即可展开或折叠的内容区域</Typography> </AccordionDetails> </Accordion>这段代码创建了一个默认展开的面板:标题右侧带一个展开图标,点击标题或图标,内容区域会带过渡动画地收起或展开。
四、三种高频定制:默认展开、换图标、禁用交互
新手最常用的三个定制点,其实都只是加一个属性,不必各写一段代码:
| 想要的效果 | 做法 |
|---|---|
| 默认展开 | 在Accordion上加defaultExpanded,首次渲染就是展开状态 |
| 换展开图标 | 给AccordionSummary的expandIcon传任意图标,如ArrowDownwardIcon,展开时的旋转动画由组件自动处理 |
| 禁用交互 | 在Accordion上加disabled,面板变灰且不再响应点击 |
另外两个常用开关也顺手记一下:square去掉圆角让它贴合列表容器,disableGutters去掉内边距让面板更紧凑。
五、受控模式:让 FAQ 页一次只展开一个面板
"手风琴"效果——点开一个、收起其余——需要把展开状态提到父组件,用expanded和onChange接管:
const [expanded, setExpanded] = React.useState('panel1'); const handleChange = (panel) => (event, isExpanded) => { setExpanded(isExpanded ? panel : false); }; <Accordion expanded={expanded === 'panel1'} onChange={handleChange('panel1')}> <AccordionSummary>第一个问题</AccordionSummary> <AccordionDetails>……</AccordionDetails> </Accordion> {/* 其余面板同理,各自绑定 handleChange('panel2') 等 */}这里用同一个状态存"当前展开的是哪块",expanded === 'panel1'这种比较让面板们互相排斥:展开新的,旧的自动收起。onChange的第二个参数isExpanded告诉你这次点击是展开还是收起,直接拿来更新状态即可。
六、进阶两件事:嵌套面板与收起时卸载内容
嵌套折叠面板用于层级化内容,写法就是在外层AccordionDetails里再放一个完整的Accordion:
<Accordion defaultExpanded> <AccordionSummary> <Typography>主面板</Typography> </AccordionSummary> <AccordionDetails> <Accordion> <AccordionSummary> <Typography>嵌套面板</Typography> </AccordionSummary> <AccordionDetails> <Typography>层级化的内容</Typography> </AccordionDetails> </Accordion> </AccordionDetails> </Accordion>注意嵌套时各层面板互不干扰,外层收起会一并隐藏子面板。
性能上有一个容易被忽略的点:默认收起的面板内容只是被视觉上藏起来,仍挂载在 DOM 里。如果面板内是图表、大表格这类重组件,建议加slotProps={{ transition: { unmountOnExit: true } }},让内容在收起时真正卸载、展开时再挂载,减少 DOM 节点和内存占用。
无障碍方面,AccordionSummary默认会自动生成aria-expanded等属性,多数场景不用手动加;如果要自定义标题结构,可以像官方示例那样给Summary加id、给Details加对应的aria-controls,保证 ARIA 无障碍语义完整。
七、常见问题速查
问:怎么只允许同时展开一个面板?答:用受控模式,把状态合并成一个变量记录当前展开的面板,各面板的expanded由它派生。
问:收起后面板内容为什么还在 DOM 里?答:这是默认行为,只是视觉隐藏。加unmountOnExit: true后收起即卸载。
问:defaultExpanded和expanded有什么区别?答:前者是"初始值",之后交给组件自己管;后者是受控的"当前值",每次变化都要靠onChange回写,二者不要同时用。
问:想去掉圆角、内边距,让面板贴边排列?答:分别加square和disableGutters两个属性,多面板纵向排列时视觉更整齐。
延伸阅读
- 官方文档:accordion.md
- 受控示例源码:ControlledAccordions.tsx
- 组件源码目录:packages/mui-material/src/Accordion/
把场景选好、状态想清楚,Material-UI 的折叠面板就能覆盖你绝大多数"内容收纳"需求。
【免费下载链接】material-uiMaterial UI: Comprehensive React component library that implements Google's Material Design. Free forever.项目地址: https://gitcode.com/GitHub_Trending/ma/material-ui
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考