背景
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}
/>
),
};
};