- 定义不同的主题色 , 如下绿,红,蓝,紫,黄, 分别定义颜色名称和颜色值
const colors = [
{ name: 'green', color: '#08bc63' }, // 绿
{ name: 'red', color: '#f5222d' }, //红
{
name: 'blue', // 蓝
color: '#004bcc',
},
{
name: 'purple', //紫
color: '#9254de',
},
{
name: 'yellow', // 黄
color: 'rgb(250, 173, 20)',
},
];
- 根据 antd-custom-theme-generator 生成相应css主题 用来动态替换 antd默认主题
-
安装 antd-custom-theme-generator
-
定义 custom-theme.less ,以黄色为例:b
@primary-color: rgb(250, 173, 20);
@link-color: rgb(250, 173, 20);
-
执行 npx generate-theme ./custom-theme.less ./custom-theme-yellow.css ,将生成custom-theme-yellow.css样色文件
-
将生成的css主题文件拷贝到 public目录
- 修改webpack devServer 配置 (当然也可以传到cdn引用)
devServer: {
historyApiFallback: true,
headers: { 'Access-Control-Allow-Origin': '*' },
setup: function (app, server) {
app.use(express.static(path.join(__dirname, `public`)));
},
},
- 定义redux store , 将颜色信息存储到redux
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider, configureStore } from 'simple-redux-store';
import { getSetting } from '~/utils/helper';
import { getEnv } from '~/utils/host';
import App from './App';
const colors = [
{ name: 'green', color: '#08bc63' },
{ name: 'red', color: '#f5222d' },
{
name: 'blue',
color: '#004bcc',
},
{
name: 'purple',
color: '#9254de',
},
{
name: 'yellow',
color: 'rgb(250, 173, 20)',
},
];
type Color = {
name: string;
color: string;
};
type StoreData = {
menuCollapsed: boolean;
isSettingVisile: boolean;
colors: Color[];
color: string; //当前颜色名称
};
const initData: StoreData = {
menuCollapsed: false,
isSettingVisile: false,
colors,
color: 'blue', //默认取蓝色
...getSetting(),
};
const store = configureStore(initData, getEnv() === 'test');
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
- 定义换肤设置面板, 这里用antd drawer 组件
读取redux colors数组, 动态生成颜色块 , 点击颜色块, 更新redux color颜色名, 动态下载对应css皮肤
import React, { useEffect } from 'react';
import { Menu, Avatar, Dropdown, Space, Button, Drawer } from 'antd';
import { useSelector, useUpdateStore } from 'simple-redux-store';
import { useHistory } from 'react-router-dom';
import { loadResource, saveSetting } from '~/utils/helper';
import {
MenuUnfoldOutlined,
MenuFoldOutlined,
UserOutlined,
SettingOutlined,
} from '@ant-design/icons';
import * as storage from 'simple-browser-store';
import styled from 'styled-components';
const StyledColorBlock = styled.div`
width: 20px;
height: 20px;
margin-top: 8px;
margin-right: 8px;
color: #fff;
font-weight: 700;
text-align: center;
border-radius: 2px;
cursor: pointer;
`;
const StyledHeader = styled.header`
display: flex;
height: 48px;
background: ${(props) => props.theme.color}; // 读取Styled Component的主题色
justify-content: space-between;
align-items: center;
padding: 0 20px;
border-bottom: 1px solid #f5f5f5;
.folder {
font-size: 16px;
color: rgba(0, 0, 0, 0.65);
&:hover {
color: #004bcc;
}
}
`;
export default function Header() {
const history = useHistory();
const { color = '', colors } = useSelector((state) => state.app);
const updateStore = useUpdateStore();
// color改变,动态加载新主题
useEffect(() => {
if (color) {
// eslint-disable-next-line no-undef
loadResource(`${__webpack_public_path__}custom-theme-${color}.css`);
}
}, [color]);
return (
<StyledHeader>
<Drawer
title="主题色设置"
placement="right"
closable={false}
onClose={() => updateStore({ isSettingVisile: false })}
visible={isSettingVisile}
>
<p>
<Space>
//动态生成颜色块
{colors.map((c, i) => (
<StyledColorBlock
onClick={() => {
updateStore({ color: c.name });
saveSetting({ color: c.name });
}}
style={{ backgroundColor: c.color }}
key={i}
/>
))}
</Space>
</p>
</Drawer>
</StyledHeader>
);
}
- Styled component 通过ThemeProvider 同步redux主题色 ,** 处理非antd组件的换肤 **
const { color = '', colors } = useSelector((state) => state.app);
<ThemeProvider theme={{ color: colors.find((c) => c.name === color).color }}>
<ConfigProvider locale={zhCN}>
<Router>
<Suspense fallback={<Spin spinning />}>
<Switch>
<Route exact path="/">
<Redirect to={'/user/add'} />
</Route>
{routes.map((route, idx) => (
<Route
key={idx}
path={route.path}
exact={route.exact}
component={route.component}
/>
))}
</Switch>
</Suspense>
</Router>
</ConfigProvider>
</ThemeProvider>
运行效果如图