ProLayout 菜单文字展示不全

225 阅读2分钟

1: 鼠标悬浮展示全部菜单文字

menuItemRender 新增 Tooltip

image.png

 menuItemRender={(
  item: MenuDataItem & {
    isUrl: boolean;
    onClick: () => void;
  },
  dom: ReactNode
) => (
  <Tooltip placement={item.isSideMenus ? 'right' : 'bottom'} color={'#094891'} title={item.name}>
    <a
      onClick={() => {
        if (item.path?.startsWith("http")) {
          if (onMenuClick) {
            if (!onMenuClick(item.path as string)) {
              window.open(item.path, "_blank");
            }
          }
        } else {
          setPathname(item.path);
          console.log("item****:", item)
          clickPageHeader(item)
          settabActiveKey(item.key ? item.key : '')

          if (item.path === process.env.basePath) {
            Router.push({ pathname: '/' });
          } else {
            window.open(item.path, '_self');
          }
        }
      }}
    >
      {dom}
    </a >
  </Tooltip>
)}

2: 菜单拖拽

拖动左侧菜单改变 siderWidth 宽度

右侧是 iframe时会出现性能问题,鼠标粘连,菜单拖动卡顿

解决方案: 在iframe同级上新增一个遮罩层,拖动菜单的时候(onmousemove)控制遮罩层显示, 鼠标停止时(onmouseup)控制遮罩层隐藏

<div className="iframeDiv" style={{
    width: '100%', 
    height: '100%', 
    position='absolute',
    zIndex: 1111, 
    filter='alpha(opacity=0)',
    background: 'transparent', 
    marginTop: '30px', 
    display: 'none'}}></div>

完整代码

useSiderDragWidth.ts

import { useEffect, useState } from "react";

interface DragSiderProps {
  initWidth?: number;
  parentClass?: string;
  initStyle?: string;
}

const useSiderDragWidth = ({
  initWidth = 220,
  parentClass = ".ant-layout-sider",
  initStyle = ` 
  position: absolute; width: 2px;
  height: 100%;
  right: 0;
  cursor: e-resize;
  z-index: 112;
  top: 0;`,
}: DragSiderProps, iframeDom: any // 接收遮罩层dom节点) => {
  const [width, setWidth] = useState(initWidth);
  useEffect(() => {
    // if (document.querySelector(parentClass)) {
    setTimeout(() => {
      let node = document.createElement("div");
      node.setAttribute(
        "style",
        `
       ${initStyle}
        `
      );
      node.onmousedown = function (e: MouseEvent) {
        e.preventDefault();
        document.onmousemove = mouseMove;
        document.onmouseup = mouseUp;
      };
      document.querySelector(parentClass)?.appendChild(node);
    }, 800)
    // }
    let event = null;
    function mouseMove(e: MouseEvent) {
    //遮罩层显示
      iframeDom[0].style.display='block';
      event = e || window.event;
      setWidth(event.clientX);
    }
    //终止事件
    function mouseUp() {
    //遮罩层隐藏
      iframeDom[0].style.display='none';
      document.onmousemove = null;
      document.onmouseup = null;
    }
  }, []);

  return { width };
};

export { useSiderDragWidth };


import { MenuDataItem } from "@ant-design/pro-layout";
import {  ReactNode } from "react";
import {useSiderDragWidth} from './useSiderDragWidth.ts'
<ProLayout
       siderWidth={useSiderDragWidth({},document.getElementsByClassName('iframeDiv')).width}
       contentStyle={{
         padding: 0,
         margin: 0,
       }}
       token={{
         bgLayout: '#fff',
         sider: {
           colorMenuBackground: 'linear-gradient(to bottom, #05274d, #05274d)',
           colorTextMenuItemHover: '',
           colorTextMenuActive: '#094891',
           colorBgMenuItemHover: '#05274d',
           colorBgMenuItemSelected: '#094891',
           colorTextMenuSelected: '#fff',
           colorTextMenu: '#fff',
         },
         header: {
           colorBgHeader: '#05274d',
           colorTextMenu: '#ffffff',
           colorHeaderTitle: '#000',
           colorTextMenuSelected: '#ffffff',
           colorTextMenuActive: '#094891',
         },

         pageContainer: {
           paddingBlockPageContainerContent: 0,
           paddingInlinePageContainerContent: 0,
         },
       }}
       {...menuData}
       location={{
         pathname,
       }}

       pageTitleRender={false}
       actionsRender={(props: HeaderViewProps) => {
         if (props.isMobile) {
           return [];
         }
         return [
           props.layout !== 'side' && document.body.clientWidth > 1400 ? (
             <div
               key="SearchOutlined"
               aria-hidden
               style={{
                 display: 'flex',
                 alignItems: 'center',
                 marginInlineEnd: 0,
               }}
               onMouseDown={(e) => {
                 e.stopPropagation();
                 e.preventDefault();
               }}
             >
               {profileMenu}
             </div>
           ) : undefined,
         ];
       }}
       menuItemRender={(
         item: MenuDataItem & {
           isUrl: boolean;
           onClick: () => void;
         },
         dom: ReactNode
       ) => (
         <Tooltip placement={item.isSideMenus ? 'right' : 'bottom'} color={'#094891'} title={item.name}>
           <a
             onClick={() => {
               if (item.path?.startsWith("http")) {
                 if (onMenuClick) {
                   if (!onMenuClick(item.path as string)) {
                     window.open(item.path, "_blank");
                   }
                 }
               } else {
                 setPathname(item.path);
                 console.log("item****:", item)
                 clickPageHeader(item)
                 settabActiveKey(item.key ? item.key : '')

                 if (item.path === process.env.basePath) {
                   Router.push({ pathname: '/' });
                 } else {
                   window.open(item.path, '_self');
                 }
               }
             }}
           >
             {dom}
           </a >
         </Tooltip>
       )}
       {...settings}
       headerTitleRender={() => {
         return (
           <div className="flex justify-center align-middle" style={{ background: 'linear-gradient(to bottom, #05274d, #05274d)', width: 220 }}>
             < img style={{ height: 35 }} src={logo} alt="" />
             <span className="font-bold" style={{ fontSize: 20, color: 'rgb(242, 249, 251)' }}>
               {title}
             </span>
           </div>
         );
       }}
     >
     //遮罩层
     <div className="iframeDiv" style={{
       width: '100%', 
       height: '100%', 
       position='absolute',
       zIndex: 1111, 
       filter='alpha(opacity=0)',
       background: 'transparent', 
       marginTop: '30px', 
       display: 'none'}}></div>
       <PageContainer>{children}</PageContainer>
</ProLayout>