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这个属性去渲染元素。
但是下面这种做法无效❌
- 在app.tsx layout这个函数里面写组件。(但是这个函数是umi在运行时读取的配置项属性,该函数返回一个配置项对象)
- 通过useState定义变量去控制collapse属性和onCollapse,然后用该变量条件渲染不同icon或者不同class
正确做法
参考了这篇博客,然后稍作修改https://blog.csdn.net/qq_41595144/article/details/120985948
- 编写一个组件作为collapsedButtonRender属性传入值
- 接收参数collapse和onCollapse回调函数
- 设置本地响应式数据collapsed,用来控制节点或者样式
- 当本地的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()方法
- 对入参进行解构,获取到initialState和setInitialState两个参数
- 定义collapse状态改变时的回调函数onCollapse,通过setInitialState来改变状态
- 将相关内容写入配置项
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}
/>
),
};
};