You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Next.js中实现MUI分离式自定义手风琴组件遇阻求助

分离式MUI手风琴实现方案

核心思路

放弃使用React Portal(易导致多面板内容挂载到同一DOM节点引发合并问题),将标题栏与内容区拆分为两个独立容器,通过全局状态关联面板的展开/收起状态,实现分离式布局的同时保证内容独立渲染。

具体实现步骤

  1. 维护展开状态:用对象存储每个面板的展开状态,键为面板唯一ID,值为布尔值。
  2. 标题栏容器:遍历数据渲染标题组件,点击时切换对应面板的状态。
  3. 内容区容器:仅渲染当前展开的面板内容,通过布局确保与标题栏位置对齐。
  4. 样式对齐:通过CSS或MUI布局组件(如Grid)保证标题与内容的对应关系。

代码示例

状态与事件处理

import { useState } from 'react';
import { AccordionSummary, AccordionDetails, Typography, ExpandMoreIcon, Grid } from '@mui/material';

const SeparateAccordion = ({ data }) => {
  // 存储各面板展开状态,key为面板ID
  const [expandedPanels, setExpandedPanels] = useState({});

  // 切换面板展开状态
  const togglePanel = (panelId) => {
    setExpandedPanels(prev => ({
      ...prev,
      [panelId]: !prev[panelId]
    }));
  };

  return (
    <Grid container spacing={2}>
      {/* 左侧标题栏 */}
      <Grid item xs={3}>
        <div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
          {data.map(item => (
            <AccordionSummary
              key={item.id}
              onClick={() => togglePanel(item.id)}
              expandIcon={<ExpandMoreIcon />}
              aria-expanded={expandedPanels[item.id] || false}
              sx={{ cursor: 'pointer', border: '1px solid #e0e0e0', borderRadius: '4px' }}
            >
              <Typography>{item.title}</Typography>
            </AccordionSummary>
          ))}
        </div>
      </Grid>

      {/* 右侧内容区 */}
      <Grid item xs={9}>
        <div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
          {data.map(item => (
            expandedPanels[item.id] && (
              <AccordionDetails
                key={item.id}
                sx={{ border: '1px solid #e0e0e0', borderRadius: '4px', padding: '16px' }}
              >
                <Typography>{item.content}</Typography>
              </AccordionDetails>
            )
          ))}
        </div>
      </Grid>
    </Grid>
  );
};

数据格式示例

const demoData = [
  { id: 'panel-1', title: '面板1', content: '面板1的详细内容...' },
  { id: 'panel-2', title: '面板2', content: '面板2的详细内容...' },
  { id: 'panel-3', title: '面板3', content: '面板3的详细内容...' },
];

关键说明

  • 每个面板必须有唯一ID,确保状态切换和渲染的准确性。
  • 内容区通过expandedPanels[item.id]判断是否渲染,避免未展开面板占用布局空间。
  • 若需纵向排列的分离式布局(标题在上、内容在下),可去掉Grid,将标题栏和内容区改为垂直排列的容器即可。

内容的提问来源于stack exchange,提问作者CADENTIC

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 07:24:25