猴爪许愿:希望后端给我接口
项目是有后端的,但是由于是同步的开发,没办法随时随地和后端沟通,和后端约定一个数据的表,前端项目在实现的时候用JsonServer模拟后端数据
要使用 ,先安装
json-server --watch db.json
可以在npm上面搜索
json-server - npmhttps://www.npmjs.com/package/json-serverJson-server是基于node重新封装的一个框架
有查询的功能:比如这样:localhost:8000/posts?id=111
这就是根据属性筛选
开启Jsonserver:
json-server --watch test.json
import React from 'react';
import { Button } from "antd";
import 'axios'
import axios from 'axios';function Home() {const ajax = ()=>{//拿取数据axios.get("https://localhost:3000/posts/2").then(res=>{console.log(res.data)})// 插入数据axios.post("http://localhost:3000/posts",{title:"hello",author:"lizhi"})}return (<div><Button type='primary' onClick={ajax}>Button</Button></div>);
}export default Home;
增数据
import React from 'react';
import { Button } from "antd";
import 'axios'
import axios from 'axios';function Home() {const ajax = ()=>{//拿取数据// _embedaxios.get("http://localhost:3000/posts?_embed=comments").then(res=>{console.log(res.data)})// _expand// axios.get("http://localhost:3000/comments?_expand=post").then(res=>{// console.log(res.data)// })// // 插入数据// axios.post("http://localhost:3000/posts",{// id:1,// title:"hello",// author:"lizhi"// })}return (<div><Button type='primary' onClick={ajax}>Button</Button></div>);
}export default Home;
后端SideMenu
import React, { useState, useEffect } from 'react'
import { Layout, theme } from 'antd'
import './index.css'
import {UploadOutlined,UserOutlined,VideoCameraOutlined,SettingOutlined,
} from '@ant-design/icons'
import { Switch } from 'antd'
// import SubMenu from 'antd/es/menu/SubMenu'
import { useNavigate } from 'react-router-dom' // 引入 useNavigate
import axios from 'axios'
import { Menu } from 'antd';
const { SubMenu } = Menu; const { Header, Content, Sider } = Layout// const menuList = [
// {
// key: '/home',
// title: '首页',
// icon: <UserOutlined />,
// },
// {
// key: '/user-manage',
// title: '用户管理',
// icon: <UserOutlined />,
// children: [
// {
// key: '/user-manage/list',
// title: '用户列表',
// icon: <UserOutlined />,
// },
// ],
// },
// {
// key: '/right-manage',
// title: '权限管理',
// icon: <UserOutlined />,
// children: [
// {
// key: '/right-manage/role/list',
// title: '角色列表',
// icon: <UserOutlined />,
// },
// {
// key: '/right-manage/right/list',
// title: '权限列表',
// icon: <UserOutlined />,
// },
// ],
// },
// ]function SideMenu(props) {const [menu, setMenu] = useState([])useEffect(() => {axios.get('http://localhost:3000/rights?_embed=children').then((res) => {console.log(res.data)setMenu(res.data)})},[])const [collapsed, setCollapsed] = useState(false)const navigate = useNavigate() // 使用 useNavigate 获取 navigate 函数const onClick = (e) => {console.log('click ', e)}const renderMenu = (menuList) => {return menuList.map((item) => {if (item.children) {return (<SubMenu key={item.key} icon={item.icon} title={item.title}>{renderMenu(item.children)}</SubMenu>)}return (<Menu.Itemkey={item.key}icon={item.icon}onClick={() => {navigate(item.key) // 使用 navigate 进行导航}}>{item.title}</Menu.Item>)})}return (<Sider trigger={null} collapsible collapsed={false}><div className="logo">新闻发布系统</div><Menutheme="dark"mode="inline"defaultSelectedKeys={['3']}onClick={onClick}defaultOpenKeys={['sub1']}>{renderMenu(menu)}</Menu></Sider>)
}export default SideMenu
用test.json模拟后端的数据:
如果没有配置permission字段的没有必要渲染(没有资格点过去)
import React, { useState, useEffect } from 'react'
import { Layout, Menu } from 'antd'
import { useNavigate } from 'react-router-dom'
import axios from 'axios'
import {UserOutlined,SettingOutlined,UploadOutlined,VideoCameraOutlined,AuditOutlined,FormOutlined,HomeOutlined,
} from '@ant-design/icons'const { SubMenu } = Menu
const { Sider } = Layout// **手动映射菜单项对应的图标**
const iconMap = {首页: <HomeOutlined />,用户管理: <UserOutlined />,用户列表: <UserOutlined />,权限管理: <SettingOutlined />,新闻管理: <FormOutlined />,审核管理: <AuditOutlined />,发布管理: <UploadOutlined />,
}function SideMenu() {const [menu, setMenu] = useState([])useEffect(() => {axios.get('http://localhost:3000/rights?_embed=children').then((res) => {setMenu(res.data)})}, [])const navigate = useNavigate()const checkPermission = (item) => {// 检查用户是否具有访问权限return item.pagepermisson === 1}const renderMenu = (menuList) => {return menuList.map((item) => {const icon = iconMap[item.title] || <VideoCameraOutlined /> // 默认图标if (item.children && checkPermission(item)) {return (<SubMenu key={item.key} icon={icon} title={item.title}>{renderMenu(item.children)}</SubMenu>)}return (checkPermission(item) &&<Menu.Item key={item.key} icon={icon} onClick={() => navigate(item.key)}>{item.title}</Menu.Item>)})}return (<Sider trigger={null} collapsible><div className="logo">新闻发布系统</div><Menu theme="dark" mode="inline" defaultSelectedKeys={['1']}>{renderMenu(menu)}</Menu></Sider>)
}export default SideMenu
这样以后就成功了,以及图标也可以正确的显示
接下来要解决的是首页不可折叠的问题
import React, { useState, useEffect } from 'react'
import { Layout, Menu } from 'antd'
import { useNavigate } from 'react-router-dom'
import axios from 'axios'
import {UserOutlined,SettingOutlined,UploadOutlined,VideoCameraOutlined,AuditOutlined,FormOutlined,HomeOutlined,
} from '@ant-design/icons'const { SubMenu } = Menu
const { Sider } = Layout// **手动映射菜单项对应的图标**
const iconMap = {首页: <HomeOutlined />,用户管理: <UserOutlined />,用户列表: <UserOutlined />,权限管理: <SettingOutlined />,新闻管理: <FormOutlined />,审核管理: <AuditOutlined />,发布管理: <UploadOutlined />,
}function SideMenu() {const [menu, setMenu] = useState([])useEffect(() => {axios.get('http://localhost:3000/rights?_embed=children').then((res) => {setMenu(res.data)})}, [])const navigate = useNavigate()const checkPermission = (item) => {// 检查用户是否具有访问权限return item.pagepermisson === 1}const renderMenu = (menuList) => {return menuList.map((item) => {const icon = iconMap[item.title] || <VideoCameraOutlined /> // 默认图标if (item.children?.length>0 && checkPermission(item)) {return (<SubMenu key={item.key} icon={icon} title={item.title}>{renderMenu(item.children)}</SubMenu>)}return (checkPermission(item) &&<Menu.Item key={item.key} icon={icon} onClick={() => navigate(item.key)}>{item.title}</Menu.Item>)})}return (<Sider trigger={null} collapsible><div className="logo">新闻发布系统</div><Menu theme="dark" mode="inline" defaultSelectedKeys={['1']}>{renderMenu(menu)}</Menu></Sider>)
}export default SideMenu
进行链式判断,如果没有的话就不判断长度
然后是进行一些样式方面的优化,把滚动条给该样式(需安装antd,因为Vite默认不支持~的写法,那种写法是Webpack的)
@import 'antd/dist/reset.css';::-webkit-scrollbar{width: 5px;height: 5px;position: absolute;}
::-webkit-scrollbar-thumb{background-color: #1890ff;}
::-webkit-scrollbar-track{background-color: #ddd;}
接下来根据路径选择渲染哪一部分高亮
重定向会导致高亮显示失效,是因为加上default会变成非受控组件,而去掉default就称为受控的了(受控:外部状态改变,内部也会受到影响
非受控:外部状态改变只对第一次的造成影响)
import React, { useState, useEffect } from 'react'
import { Layout, Menu } from 'antd'
import { useNavigate } from 'react-router-dom'
import axios from 'axios'
import {UserOutlined,SettingOutlined,UploadOutlined,VideoCameraOutlined,AuditOutlined,FormOutlined,HomeOutlined,
} from '@ant-design/icons'
import './index.css'
import { useLocation } from 'react-router-dom'const { SubMenu } = Menu
const { Sider } = Layout// **手动映射菜单项对应的图标**
const iconMap = {首页: <HomeOutlined />,用户管理: <UserOutlined />,用户列表: <UserOutlined />,权限管理: <SettingOutlined />,新闻管理: <FormOutlined />,审核管理: <AuditOutlined />,发布管理: <UploadOutlined />,
}function SideMenu() {const [menu, setMenu] = useState([])const location = useLocation() // 获取当前的路径useEffect(() => {axios.get('http://localhost:3000/rights?_embed=children').then((res) => {setMenu(res.data)})}, [])const navigate = useNavigate()const checkPermission = (item) => {// 检查用户是否具有访问权限return item.pagepermisson === 1}const renderMenu = (menuList) => {return menuList.map((item) => {const icon = iconMap[item.title] || <VideoCameraOutlined /> // 默认图标if (item.children?.length > 0 && checkPermission(item)) {return (<SubMenu key={item.key} icon={icon} title={item.title}>{renderMenu(item.children)}</SubMenu>)}return (checkPermission(item) && (<Menu.Itemkey={item.key}icon={icon}onClick={() => navigate(item.key)}>{item.title}</Menu.Item>))})}//找到路径const selectKeys = [location.pathname]//分割字符串const openKeys = ['/' + location.pathname.split('/')[1]]return (<Sider trigger={null} collapsible><div style={{ display: 'flex', height: '100%', flexDirection: 'column' }}><div className="logo">新闻发布系统</div><div style={{ flex: 1, overflow: 'auto' }}><Menutheme="dark"mode="inline"selectedKeys={selectKeys}defaultOpenKeys={openKeys}>{renderMenu(menu)}</Menu></div></div></Sider>)
}export default SideMenu