Umi4菜单栏将collapse按钮放置底部

背景

Umi@4中菜单栏的collapse按钮默认不在菜单栏底部,需求要将该按钮放回菜单底部并且改变默认icon

 

一开始做法

  • 直接修改组件样式,将其放置到菜单组件底部
  • 但是无法修改icon
    • 不想使用伪元素去重写icon,而且无法做到不同状态不同icon
  • .ant-pro-sider-collapsed-button {
        bottom: 0;
        left: 0;
        width: 100%;
        height: 44px;
        padding: 0 !important;
        border-radius: unset;
        border-top: 1px solid #e8eaeb;
        box-shadow: none;
        inset-block-start: unset;
    
        svg {
            color: #999;
            font-size: 18px;
        }
    }

     

于是希望能在配置项里面进行更改,但是没有提供仅更改icon的属性,只有提供collapsedButtonRender这个属性去渲染元素。

但是下面这种做法无效❌

  1. 在app.tsx layout这个函数里面写组件。(但是这个函数是umi在运行时读取的配置项属性,该函数返回一个配置项对象)
  2. 通过useState定义变量去控制collapse属性和onCollapse,然后用该变量条件渲染不同icon或者不同class

 

正确做法

参考了这篇博客,然后稍作修改https://blog.csdn.net/qq_41595144/article/details/120985948

  1. 编写一个组件作为collapsedButtonRender属性传入值
    1. 接收参数collapse和onCollapse回调函数
    2. 设置本地响应式数据collapsed,用来控制节点或者样式
    3. 当本地的collapsed改变后,调用onCollapse,通知调用者collapse状态改变
import { MenuUnfoldOutlined } from '@ant-design/icons';
import { FC, memo, useEffect, useState } from 'react';
import './index.less';

interface Props {
  collapse?: boolean;
  onCollapse?: (collapsed: boolean) => void;
}
export const Index: FC<Props> = memo(({ collapse, onCollapse }) => {
  const [collapsed, setCollapsed] = useState<boolean>(collapse ?? false);

  useEffect(() => {
    if (collapse) {
      setCollapsed(collapse);
    }
  }, [collapse]);

  useEffect(() => {
    if (onCollapse) {
      onCollapse(collapsed);
    }
  }, [collapsed]);

  return (
    <div
      className={
        collapsed
          ? 'menu-collapsed-button menu-collapsed-button-active'
          : 'menu-collapsed-button'
      }
      onClick={() => setCollapsed(!collapsed)}
    >
      <MenuUnfoldOutlined />
    </div>
  );
});
export default Index;

2. 修改app.tsx getInitialState()方法,增加collapse类型

3.修改app.tsx layout()方法

  1. 对入参进行解构,获取到initialState和setInitialState两个参数
  2. 定义collapse状态改变时的回调函数onCollapse,通过setInitialState来改变状态
  3. 将相关内容写入配置项
export const layout: RunTimeLayoutConfig = ({
  initialState,
  setInitialState,
}) => {
  const onCollapse = (collapsed: boolean) => {
    setInitialState({ ...initialState, collapsed } as any).then();
  };
  return {
    ...
    collapsed: initialState?.collapsed,
    onCollapse: onCollapse,
    collapsedButtonRender: () => (
      <MenuCollapseButton
        collapse={initialState?.collapsed}
        onCollapse={onCollapse}
      />
    ),
  };
};

 

posted @ 2024-08-14 16:51  Karle  阅读(44)  评论(0编辑  收藏  举报