wordpress建站要多久,网站建设 锐颖科技,wordpress 词库,企业年报网上申报入口免费官方前言 本文将引导开发者从零基础开始#xff0c;运用vite、react、react-router、react-redux、Ant Design、less、tailwindcss、axios等前沿技术栈#xff0c;构建一个高效、响应式的后台管理系统。通过详细的步骤和实践指导#xff0c;文章旨在为开发者揭示如何利用这些技术… 前言 本文将引导开发者从零基础开始运用vite、react、react-router、react-redux、Ant Design、less、tailwindcss、axios等前沿技术栈构建一个高效、响应式的后台管理系统。通过详细的步骤和实践指导文章旨在为开发者揭示如何利用这些技术工具从项目构思到最终实现的全过程提供清晰的开发思路和实用的技术应用技巧。 项目gitee地址lbking666666/enqi-admin 本系列文章
使用vitereacttsAnt Design开发后台管理项目一使用vitereacttsAnt Design开发后台管理项目二使用vitereacttsAnt Design开发后台管理项目三使用vitereacttsAnt Design开发后台管理项目四
添加配置 添加设置按钮
目前头部只有一个控制左侧菜单的按钮需要在右侧添加一个按钮可以设置整体的一些配置。修改layout文件夹下的header.tsx文件
//layout/header.tsx
import React from react;
import { Button, Layout, theme } from antd;
import { MenuFoldOutlined, MenuUnfoldOutlined,SettingOutlined } from ant-design/icons;
const { Header } Layout;
interface AppSiderProps {collapsed: boolean;
}
const AppHeader: React.FCAppSiderProps ({ collapsed }) {const {token: { colorBgContainer },} theme.useToken();return (Header style{{ padding: 0, background: colorBgContainer }}Flex gapmiddle justifyspace-between aligncenterButtontypetexticon{collapsed ? MenuUnfoldOutlined / : MenuFoldOutlined /}style{{fontSize: 16px,width: 64,height: 64,}}onClick{handleCollapsed}/ButtontypeprimaryclassNamemr-4icon{SettingOutlined /}//Flex/Header);
};
export default AppHeader;
添加Drawer抽屉
从Ant Design选择抽屉组件截图如下 把这里的代码拿到layout文件夹下的header.tsx文件中
//layout/header.tsximport React, { useState } from react;
import { Button, Layout, theme, Flex, Drawer } from antd;
import {MenuFoldOutlined,MenuUnfoldOutlined,SettingOutlined,
} from ant-design/icons;
import { useAppDispatch } from /hooks/UseGlobal.hooks;
import { setCollapsed } from /store/reducers/global;
const { Header } Layout;
interface AppSiderProps {collapsed: boolean;
}const AppHeader: React.FCAppSiderProps ({ collapsed }) {const {token: { colorBgContainer },} theme.useToken();const [showPoup, setShowPoup] useState(false);const dispatch useAppDispatch();//收缩事件const handleCollapsed () {//更新全局状态 collapseddispatch(setCollapsed());};//设置按钮点击事件const handleShowPoup () {console.log(点击了按钮);setShowPoup(true);};const onClose () {setShowPoup(false);};return (Header style{{ padding: 0, background: colorBgContainer }}Flex gapmiddle justifyspace-between aligncenterButtontypetexticon{collapsed ? MenuUnfoldOutlined / : MenuFoldOutlined /}style{{fontSize: 16px,width: 64,height: 64,}}onClick{handleCollapsed}/ButtontypeprimaryclassNamemr-4icon{SettingOutlined /}onClick{handleShowPoup}//FlexDrawer titleBasic Drawer onClose{onClose} open{showPoup}pSome contents.../ppSome contents.../ppSome contents.../p/Drawer/Header);
};
export default AppHeader; 查看效果发现关闭按钮在左侧一般我们习惯把关闭按钮放到右侧根据Ant Design的Drawer的api我们可以设置closeIcon和extra这两个
//layout/header.tsx
import React, { useState } from react;
import { Button, Layout, theme, Flex, Drawer,Space } from antd;
import {MenuFoldOutlined,MenuUnfoldOutlined,SettingOutlined,CloseOutlined
} from ant-design/icons;
import { useAppDispatch } from /hooks/UseGlobal.hooks;
import { setCollapsed } from /store/reducers/global;
const { Header } Layout;
interface AppSiderProps {collapsed: boolean;
}const AppHeader: React.FCAppSiderProps ({ collapsed }) {const {token: { colorBgContainer },} theme.useToken();const [showPoup, setShowPoup] useState(false);const dispatch useAppDispatch();//收缩事件const handleCollapsed () {//更新全局状态 collapseddispatch(setCollapsed());};//设置按钮点击事件const handleShowPoup () {console.log(点击了按钮);setShowPoup(true);};const onClose () {setShowPoup(false);};return (Header style{{ padding: 0, background: colorBgContainer }}Flex gapmiddle justifyspace-between aligncenterButtontypetexticon{collapsed ? MenuUnfoldOutlined / : MenuFoldOutlined /}style{{fontSize: 16px,width: 64,height: 64,}}onClick{handleCollapsed}/ButtontypeprimaryclassNamemr-4icon{SettingOutlined /}onClick{handleShowPoup}//FlexDrawertitle设置closeIcon{false}open{showPoup}extra{SpaceButton typelink onClick{onClose} icon{CloseOutlined /}/Button/Space}/Drawer/Header);
};
export default AppHeader;效果如下图这里关闭按钮在右侧了 添加设置项
这里的查看Ant Design官网后选择了三项设置主题颜色的配置暗黑模式、圆角模式 先把这三个内容添加进来控制这三个的响应式变量先使用useState在头部组件中定义出来等调试好之后再更换为redux状态管理
//layout/header.tsx
import React, { useState } from react;
import { Button, Layout, theme, Flex, Drawer, Space, Switch } from antd;
import {MenuFoldOutlined,MenuUnfoldOutlined,SettingOutlined,CloseOutlined,CheckOutlined,
} from ant-design/icons;
import { useAppDispatch } from /hooks/UseGlobal.hooks;
import { setCollapsed } from /store/reducers/global;
const { Header } Layout;
interface AppSiderProps {collapsed: boolean;
}
const colors [{name: 拂晓蓝,value: #1677ff,},{name: 薄暮,value: #5f80c7,},{name: 日暮,value: #faad14,},{name: 火山,value: #f5686f,},{name: 酱紫,value: #9266f9,},{name: 极光绿,value: #3c9,},{name: 极客蓝,value: #32a2d4,},
];const AppHeader: React.FCAppSiderProps ({ collapsed }) {const {token: { colorBgContainer },} theme.useToken();//抽屉弹出const [showPoup, setShowPoup] useState(false);const [curColor, setCurColor] useState(#1677ff);const [isSelectdDark, setIsSelectdDark] useState(false);const [isSelectdRadius, setIsSelectdRadius] useState(false);const onChangeDark (checked: boolean) {setIsSelectdDark(checked);};const onChangeRadius (checked: boolean) {setIsSelectdRadius(checked);};const handlesetCurColor (color: string) {setCurColor(color);};const ColorItem: React.FC{ color: string; isSelectd: boolean } ({color,isSelectd,}) {if (isSelectd) {return (divclassNamew-6 h-6 flex justify-center items-center rounded cursor-pointer itemsstyle{{ background: color }}CheckOutlined style{{ color: #fff }} //div);} else {return (divclassNamew-6 h-6 flex justify-center items-center rounded cursor-pointer itemsstyle{{ background: color }}onClick{() handlesetCurColor(color)}/div);}};const dispatch useAppDispatch();//收缩事件const handleCollapsed () {//更新全局状态 collapseddispatch(setCollapsed());};//设置按钮点击事件const handleShowPoup () {setShowPoup(true);};const onClose () {setShowPoup(false);};return (Header style{{ padding: 0, background: colorBgContainer }}Flex gapmiddle justifyspace-between aligncenterButtontypetexticon{collapsed ? MenuUnfoldOutlined / : MenuFoldOutlined /}style{{fontSize: 16px,width: 64,height: 64,}}onClick{handleCollapsed}/ButtontypeprimaryclassNamemr-4icon{SettingOutlined /}onClick{handleShowPoup}//FlexDrawertitle设置width{300}closeIcon{false}open{showPoup}extra{SpaceButtontypetextonClick{onClose}icon{CloseOutlined /}/Button/Space}div classNamemb-3 font-bold主题颜色/divFlex gapmiddle justifyspace-between aligncenter{colors.map((item) (ColorItemkey{item.value}color{item.value}isSelectd{curColor item.value}/))}/Flexdiv classNamemb-3 mt-3 font-bold主题模式/divdiv classNameflex justify-betweendiv classNameflex gap-2span开启暗黑模式/span/divdiv classNameflex gap-2Switch defaultChecked checked{isSelectdDark} onChange{onChangeDark} //div/divdiv classNameflex justify-betweendiv classNameflex gap-2span开启圆角主题/span/divdiv classNameflex gap-2Switch defaultChecked checked{isSelectdRadius} onChange{onChangeRadius} //div/div/Drawer/Header);
};
export default AppHeader;此时查看效果如下图修改主题颜色、暗黑模式、圆角模式都可以得到对应的效果 改造global.ts
把三个设置项和设置drawer显隐状态抽离到之前的global.ts文件中
//store/reducers/global.ts
import { createSlice } from reduxjs/toolkit;
import type { RootState } from /store/index.ts;// 定义初始 state 的类型
interface GlobalState {collapsed: boolean;//是否折叠showSetting: boolean;//是否显示设置colorPrimary: string;//主题颜色isDark: boolean;//是否暗黑模式isRadius:boolean;//是否圆角
}
// 使用该类型定义初始 state
const initialState: GlobalState {collapsed: false,showSetting: false,colorPrimary: #1677ff,isDark: false,isRadius:true
};
// 创建 slice
export const globalSlice createSlice({name: global, // 名称initialState, // 初始 statereducers: {// 定义 reducer 函数该函数接受 state 和 action 作为参数setCollapsed: (state) {// 更新 statestate.collapsed !state.collapsed;},setShowSetting: (state,action) {// 更新设置状态为 action 载荷state.showSetting action.payload;},setIsDark: (state) {// 更新暗黑模式状态state.isDark !state.isDark;},setColorPrimary: (state, action) {// 更新主题颜色为 action 载荷state.colorPrimary action.payload;},setIsRadius: (state) {// 更新圆角状态state.isRadius !state.isRadius;},},
});// 为每个 case reducer 函数生成 Action creators
export const { setCollapsed, setIsDark, setColorPrimary,setShowSetting,setIsRadius } globalSlice.actions;
// selectors 等其他代码可以使用导入的 RootState 类型
export const selectCollapsed (state: RootState) state.global.collapsed;
export const selectShowSetting (state: RootState) state.global.showSetting;
export const selectColorPrimary (state: RootState) state.global.colorPrimary;
export const selectIsDark (state: RootState) state.global.isDark;
export const selectIsRadius (state: RootState) state.global.isRadius;
// 导出 reducer
export default globalSlice.reducer;添加设置项组件
把设置项drawer的代码抽离到单独的组件中在layout文件夹下新增setting.tsx
//layout/setting.tsx
import React, { useState } from react;
import { Button, Flex, Drawer, Space, Switch } from antd;
import { CloseOutlined, CheckOutlined } from ant-design/icons;
const colors [{name: 拂晓蓝,value: #1677ff,},{name: 薄暮,value: #5f80c7,},{name: 日暮,value: #faad14,},{name: 火山,value: #f5686f,},{name: 酱紫,value: #9266f9,},{name: 极光绿,value: #3c9,},{name: 极客蓝,value: #32a2d4,},
];
const Setting () {const [showPoup, setShowPoup] useState(false);const [curColor, setCurColor] useState(#1677ff);const [isSelectdDark, setIsSelectdDark] useState(false);const [isSelectdRadius, setIsSelectdRadius] useState(false);const onChangeDark (checked: boolean) {setIsSelectdDark(checked);};const onChangeRadius (checked: boolean) {setIsSelectdRadius(checked);};const handlesetCurColor (color: string) {setCurColor(color);};const onClose () {setShowPoup(false);};const ColorItem: React.FC{ color: string; isSelectd: boolean } ({color,isSelectd,}) {if (isSelectd) {return (divclassNamew-6 h-6 flex justify-center items-center rounded cursor-pointer itemsstyle{{ background: color }}CheckOutlined style{{ color: #fff }} //div);} else {return (divclassNamew-6 h-6 flex justify-center items-center rounded cursor-pointer itemsstyle{{ background: color }}onClick{() handlesetCurColor(color)}/div);}};return (Drawertitle设置width{300}closeIcon{false}open{showPoup}extra{SpaceButtontypetextonClick{onClose}icon{CloseOutlined /}/Button/Space}div classNamemb-3 font-bold主题颜色/divFlex gapmiddle justifyspace-between aligncenter{colors.map((item) (ColorItemkey{item.value}color{item.value}isSelectd{curColor item.value}/))}/Flexdiv classNamemb-3 mt-3 font-bold主题模式/divdiv classNameflex justify-between mb-3div classNameflex gap-2span开启暗黑模式/span/divdiv classNameflex gap-2SwitchdefaultCheckedchecked{isSelectdDark}onChange{onChangeDark}//div/divdiv classNameflex justify-betweendiv classNameflex gap-2span开启圆角主题/span/divdiv classNameflex gap-2SwitchdefaultCheckedchecked{isSelectdRadius}onChange{onChangeRadius}//div/div/Drawer);
};export default Setting;组件中应用redux状态
头部组件
//laout/header.tsx
import React, { useState } from react;
import { Button, Flex, Drawer, Space, Switch } from antd;
import { CloseOutlined, CheckOutlined } from ant-design/icons;
const colors [{name: 拂晓蓝,value: #1677ff,},{name: 薄暮,value: #5f80c7,},{name: 日暮,value: #faad14,},{name: 火山,value: #f5686f,},{name: 酱紫,value: #9266f9,},{name: 极光绿,value: #3c9,},{name: 极客蓝,value: #32a2d4,},
];
const Setting () {const [showPoup, setShowPoup] useState(false);const [curColor, setCurColor] useState(#1677ff);const [isSelectdDark, setIsSelectdDark] useState(false);const [isSelectdRadius, setIsSelectdRadius] useState(false);const onChangeDark (checked: boolean) {setIsSelectdDark(checked);};const onChangeRadius (checked: boolean) {setIsSelectdRadius(checked);};const handlesetCurColor (color: string) {setCurColor(color);};const onClose () {setShowPoup(false);};const ColorItem: React.FC{ color: string; isSelectd: boolean } ({color,isSelectd,}) {if (isSelectd) {return (divclassNamew-6 h-6 flex justify-center items-center rounded cursor-pointer itemsstyle{{ background: color }}CheckOutlined style{{ color: #fff }} //div);} else {return (divclassNamew-6 h-6 flex justify-center items-center rounded cursor-pointer itemsstyle{{ background: color }}onClick{() handlesetCurColor(color)}/div);}};return (Drawertitle设置width{300}closeIcon{false}open{showPoup}extra{SpaceButtontypetextonClick{onClose}icon{CloseOutlined /}/Button/Space}div classNamemb-3 font-bold主题颜色/divFlex gapmiddle justifyspace-between aligncenter{colors.map((item) (ColorItemkey{item.value}color{item.value}isSelectd{curColor item.value}/))}/Flexdiv classNamemb-3 mt-3 font-bold主题模式/divdiv classNameflex justify-between mb-3div classNameflex gap-2span开启暗黑模式/span/divdiv classNameflex gap-2SwitchdefaultCheckedchecked{isSelectdDark}onChange{onChangeDark}//div/divdiv classNameflex justify-betweendiv classNameflex gap-2span开启圆角主题/span/divdiv classNameflex gap-2SwitchdefaultCheckedchecked{isSelectdRadius}onChange{onChangeRadius}//div/div/Drawer);
};export default Setting;设置组件
//layout/setting.tsx
import React from react;
import { Button, Flex, Drawer, Space, Switch } from antd;
import { CloseOutlined, CheckOutlined } from ant-design/icons;
import { useAppSelector,useAppDispatch } from /hooks/UseGlobal.hooks;
import { selectColorPrimary,selectIsDark,selectIsRadius,setIsDark, setColorPrimary,setShowSetting,setIsRadius } from /store/reducers/global;
const colors [{name: 拂晓蓝,value: #1677ff,},{name: 薄暮,value: #5f80c7,},{name: 日暮,value: #faad14,},{name: 火山,value: #f5686f,},{name: 酱紫,value: #9266f9,},{name: 极光绿,value: #3c9,},{name: 极客蓝,value: #32a2d4,},
];
type AppSiderProps {showPoup: boolean;
}
const Setting:React.FCAppSiderProps ({showPoup}) {const curColor useAppSelector(selectColorPrimary);const isSelectdDark useAppSelector(selectIsDark);const isSelectdRadius useAppSelector(selectIsRadius);const dispatch useAppDispatch();const onChangeDark () {dispatch(setIsDark());};const onChangeRadius () {dispatch(setIsRadius());};const handlesetCurColor (color: string) {dispatch(setColorPrimary(color));};const onClose () {dispatch(setShowSetting(false));};const ColorItem: React.FC{ color: string; isSelectd: boolean } ({color,isSelectd,}) {if (isSelectd) {return (divclassNamew-6 h-6 flex justify-center items-center rounded cursor-pointer itemsstyle{{ background: color }}CheckOutlined style{{ color: #fff }} //div);} else {return (divclassNamew-6 h-6 flex justify-center items-center rounded cursor-pointer itemsstyle{{ background: color }}onClick{() handlesetCurColor(color)}/div);}};return (Drawertitle设置width{300}closeIcon{false}open{showPoup}extra{SpaceButtontypetextonClick{onClose}icon{CloseOutlined /}/Button/Space}div classNamemb-3 font-bold主题颜色/divFlex gapmiddle justifyspace-between aligncenter{colors.map((item) (ColorItemkey{item.value}color{item.value}isSelectd{curColor item.value}/))}/Flexdiv classNamemb-3 mt-3 font-bold主题模式/divdiv classNameflex justify-between mb-3div classNameflex gap-2span开启暗黑模式/span/divdiv classNameflex gap-2SwitchdefaultCheckedchecked{isSelectdDark}onChange{onChangeDark}//div/divdiv classNameflex justify-betweendiv classNameflex gap-2span开启圆角主题/span/divdiv classNameflex gap-2SwitchdefaultCheckedchecked{isSelectdRadius}onChange{onChangeRadius}//div/div/Drawer);
};export default Setting;本地存储
设置了不同的主题和是否选择暗黑模式、圆角模式后我们希望使用者在下次进入到系统时候能继续使用之前的选择这时我们需要对global.ts的状态管理做一些改造把状态存储到本地存储中
//store/reducers/global.ts
import { createSlice } from reduxjs/toolkit;
import type { RootState } from /store/index.ts;// 定义初始 state 的类型
interface GlobalState {collapsed: boolean; //是否折叠showSetting: boolean; //是否显示设置colorPrimary: string; //主题颜色isDark: boolean; //是否暗黑模式isRadius: boolean; //是否圆角
}
const getLocal (type:string) {//获取本地存储return localStorage.getItem(type);
};
// 使用该类型定义初始 state
const initialState: GlobalState {collapsed: getLocal(collapsed)true || false,showSetting: false,colorPrimary: getLocal(colorPrimary) || #1677ff,isDark: getLocal(isDark) true || false,isRadius: getLocal(isRadius)!false || true,
};
const setLocal (type:string,value: string | boolean){if (typeof value string) {localStorage.setItem(type, value);
} else {// 可以选择忽略非字符串值或者进行转换处理// 例如将布尔值转换为字符串localStorage.setItem(type, value.toString());
}
}
// 创建 slice
export const globalSlice createSlice({name: global, // 名称initialState, // 初始 statereducers: {// 定义 reducer 函数该函数接受 state 和 action 作为参数setCollapsed: (state) {// 更新 statestate.collapsed !state.collapsed;setLocal(collapsed,state.collapsed);},setShowSetting: (state, action) {// 更新设置状态为 action 载荷state.showSetting action.payload;},setIsDark: (state) {// 更新暗黑模式状态state.isDark !state.isDark;setLocal(isDark,state.isDark);},setColorPrimary: (state, action) {// 更新主题颜色为 action 载荷state.colorPrimary action.payload;setLocal(colorPrimary,action.payload);},setIsRadius: (state) {// 更新圆角状态state.isRadius !state.isRadius;setLocal(isRadius,state.isRadius);},},
});// 为每个 case reducer 函数生成 Action creators
export const {setCollapsed,setIsDark,setColorPrimary,setShowSetting,setIsRadius,
} globalSlice.actions;
// selectors 等其他代码可以使用导入的 RootState 类型
export const selectCollapsed (state: RootState) state.global.collapsed;
export const selectShowSetting (state: RootState) state.global.showSetting;
export const selectColorPrimary (state: RootState) state.global.colorPrimary;
export const selectIsDark (state: RootState) state.global.isDark;
export const selectIsRadius (state: RootState) state.global.isRadius;
// 导出 reducer
export default globalSlice.reducer;此时我们选择不同的设置 刷新页面后可以看到就是之前设置好的配置 总结
到此我们对全局配置的一个大概的工作完成了当然实际项目和需求中可能会有不同或更多的配置按照这个思路可以添加不同的配置当然如果已经很熟练的使用reactredux可以直接省略掉很多中间的步骤 比如直接新建setting.tsx子组件写逻辑和直接在global.ts中添加状态管理及方法在组件中直接应用。
后续
本篇文章为项目使用redux配合本地存储做了全局设置代码已经同步到了gitee仓库下一篇会使用axios和mock来设置左侧菜单