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

React中如何将Material-UI Drawer宽度设置为其子组件的宽度?

动态获取Drawer子组件宽度实现内容自适应收缩

我懂你现在的需求——想要让Drawer的宽度自动匹配<YourProfile>的实际渲染宽度,替代固定值,这样Drawer展开时左侧内容能完美适配、不会出现重叠。下面是具体的实现方案:

核心思路

我们通过React Refs获取<YourProfile>的实际宽度,再把这个值动态应用到Drawer的宽度设置中,同时调整左侧内容的可用空间,避免内容重叠。另外还要考虑窗口大小变化、组件内容动态更新的场景,确保宽度能实时同步。

修改后的完整代码

import { useState, useRef, useEffect } from "react";
// Material UI components
import { Box, Button, Drawer, Divider, Grid, IconButton } from "@mui/material";
// Components
import DashboardHeader from "./DashboardHeader/DashboardHeader";
import LeadershipProfile from "./LeadershipProfile/LeadershipProfile";
import YourProfile from "./YourProfile/YourProfile";
import CustomIcon from "components/CustomIcon";
import icons from "enums/icons";
import { Theme } from "@mui/material/styles";
import makeStyles from "@mui/styles/makeStyles";
import createStyles from "@mui/styles/createStyles";

const useStyles = makeStyles((theme: Theme) => createStyles({
  leftSideContainer: {
    display: "contents",
    overflow: "auto",
    textAlign: "center",
    flexGrow: 1, // 让左侧容器占满剩余可用空间
  },
  drawer: {
    top: theme.spacing(9),
    "& .MuiDrawer-paper": {
      marginTop: "72px",
      position: "absolute",
      // 移除固定宽度,后续用sx动态赋值
    },
  },
  drawerButton: {
    color: theme.palette.button.active.from,
    height: "14px",
  },
}) );

const PaceLabsDashboard = () => {
  const classes = useStyles();
  const [isDrawerOpen, setIsDrawerOpen] = useState(true);
  const [drawerContentWidth, setDrawerContentWidth] = useState(0);
  const profileRef = useRef<HTMLDivElement>(null); // 创建Ref绑定到YourProfile的外层容器

  // 获取YourProfile的实际宽度
  const getProfileWidth = () => {
    if (profileRef.current) {
      setDrawerContentWidth(profileRef.current.offsetWidth);
    }
  };

  // 组件挂载后获取初始宽度,同时监听窗口resize更新宽度
  useEffect(() => {
    getProfileWidth();
    window.addEventListener("resize", getProfileWidth);
    return () => {
      window.removeEventListener("resize", getProfileWidth);
    };
  }, []);

  // 监听YourProfile自身尺寸变化(应对内容动态更新的场景)
  useEffect(() => {
    if (!profileRef.current) return;
    const observer = new ResizeObserver(getProfileWidth);
    observer.observe(profileRef.current);
    return () => {
      observer.disconnect();
    };
  }, []);

  return (
    <Box>
      {/* Header */}
      <Box sx={{ border: "2px solid black", width: "100%", height: "72px", textAlign: "center" }}>
        <DashboardHeader />
      </Box>
      <Box sx={{ display: "flex", width: "100%" }}>
        {/* 右侧内容区域 */}
        <Box 
          className={classes.leftSideContainer}
          sx={{
            // Drawer展开时,给左侧容器设置marginRight,留出Drawer的宽度
            ...(isDrawerOpen ? { marginRight: `${drawerContentWidth}px` } : { marginRight: 0 })
          }}
        >
          <LeadershipProfile />
          <IconButton size="small" aria-label="toggle-drawer" onClick={() => setIsDrawerOpen(!isDrawerOpen)}>
            <CustomIcon className={classes.drawerButton} icon={isDrawerOpen ? icons.chevronRightThin : icons.chevronLeftThin} />
          </IconButton>
        </Box>
        {/* 左侧Drawer区域 */}
        <Drawer 
          anchor="right" 
          variant="persistent" 
          open={isDrawerOpen} 
          className={classes.drawer}
          sx={{
            display: isDrawerOpen ? "flex" : { xs: "block", sm: "none" },
            "& .MuiDrawer-paper": {
              width: `${drawerContentWidth}px`, // 动态设置Drawer宽度
            }
          }}
        >
          {/* 将Ref绑定到YourProfile的外层容器 */}
          <Box ref={profileRef}>
            <YourProfile />
          </Box>
        </Drawer>
      </Box>
    </Box>
  );
};

export default PaceLabsDashboard;

关键细节说明

  • Ref获取实际宽度:通过profileRef绑定到<YourProfile>的外层容器,直接拿到组件渲染后的真实宽度。
  • 多场景宽度同步:
    • 窗口resize监听:确保窗口大小变化时,宽度能实时更新。
    • ResizeObserver监听:如果<YourProfile>的内容是动态加载或变化的,这个API能监听元素自身的尺寸变化,比单纯的窗口resize更精准。
  • 动态样式适配:给左侧容器设置marginRight,Drawer展开时自动留出对应宽度,彻底避免内容重叠;同时将Drawer的宽度设置为获取到的实际值,保证Drawer完全贴合子组件尺寸。

这样修改后,Drawer的宽度会完全匹配<YourProfile>的实际宽度,展开时左侧内容也会自动收缩,完美解决重叠问题!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 19:22:40