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

如何将Material UI makeStyles转Emotion?求可调整抽屉代码转换示例

可调整大小的Material UI 5抽屉(Emotion版本)

下面是转换后的完整代码,替换原makeStyles为Emotion的styled API,适配Material UI 5:

import React, { useState, useRef, useEffect } from 'react';
import styled from '@emotion/styled';
import { Drawer as MuiDrawer } from '@mui/material';

// 基于MUI Drawer扩展样式
const Drawer = styled(MuiDrawer)`
  .MuiDrawer-paper {
    position: relative;
    overflow: hidden;
  }
`;

// 自定义抽屉容器,支持动态宽度
const DrawerPaper = styled.div`
  width: ${props => props.width}px;
  height: 100%;
  position: relative;
  transition: width 0.2s ease;
`;

// 拖拽调整条样式
const Resizer = styled.div`
  position: absolute;
  top: 0;
  right: 0;
  width: 5px;
  height: 100%;
  cursor: col-resize;
  background-color: rgba(0, 0, 0, 0.1);

  &:hover {
    background-color: rgba(0, 0, 0, 0.3);
  }
`;

const CustomDrawer = ({ open, onClose, children, initialWidth = 300, minWidth = 200, maxWidth = 600 }) => {
  const [width, setWidth] = useState(initialWidth);
  const isResizing = useRef(false);
  const startX = useRef(0);
  const startWidth = useRef(0);

  const handleMouseDown = (e) => {
    isResizing.current = true;
    startX.current = e.clientX;
    startWidth.current = width;
    document.addEventListener('mousemove', handleMouseMove);
    document.addEventListener('mouseup', handleMouseUp);
  };

  const handleMouseMove = (e) => {
    if (!isResizing.current) return;
    const deltaX = e.clientX - startX.current;
    const newWidth = startWidth.current + deltaX;
    if (newWidth >= minWidth && newWidth <= maxWidth) {
      setWidth(newWidth);
    }
  };

  const handleMouseUp = () => {
    isResizing.current = false;
    document.removeEventListener('mousemove', handleMouseMove);
    document.removeEventListener('mouseup', handleMouseUp);
  };

  useEffect(() => {
    return () => {
      // 组件卸载时清理事件监听
      document.removeEventListener('mousemove', handleMouseMove);
      document.removeEventListener('mouseup', handleMouseUp);
    };
  }, []);

  return (
    <Drawer
      variant="persistent"
      anchor="left"
      open={open}
      onClose={onClose}
    >
      <DrawerPaper width={width}>
        {children}
        <Resizer onMouseDown={handleMouseDown} />
      </DrawerPaper>
    </Drawer>
  );
};

export default CustomDrawer;

关键转换说明

  • 替换makeStyles为Emotion styled:将原样式定义全部迁移到styled组件中,通过props传递动态值(如抽屉宽度),实现响应式样式变化。
  • 保留MUI组件特性:直接基于MUI原生Drawer扩展样式,保留原组件的所有props(如open、onClose)。
  • 动态样式传递:抽屉宽度通过DrawerPaper的width props实时传递,替代原makeStyles中的动态样式函数。
  • 拖拽逻辑完整保留:原有的鼠标事件监听逻辑未做修改,确保调整大小的功能正常运行。

使用示例

import CustomDrawer from './CustomDrawer';
import { useState } from 'react';

function App() {
  const [drawerOpen, setDrawerOpen] = useState(true);

  return (
    <div>
      <button onClick={() => setDrawerOpen(!drawerOpen)}>切换抽屉</button>
      <CustomDrawer
        open={drawerOpen}
        onClose={() => setDrawerOpen(false)}
        initialWidth={300}
        minWidth={200}
        maxWidth={600}
      >
        <div style={{ padding: '16px' }}>
          <h2>可调整大小的抽屉</h2>
          <p>拖动右侧边缘调整宽度</p>
        </div>
      </CustomDrawer>
    </div>
  );
}

export default App;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 18:01:22