上会整理了react+ts项目初始化和添加craco配置,这回梳理react-router和网络请求封装,以及antd的使用
1.安装router和配置router antd
router使用的版本是6.8.1
1.安装依赖 npm install react-router-dom npm install antd
2.配置路由
src下创建router目录,里面创建config.tsx配置文件,可以将所有路由配置在这里,也可以编写路由拦截
import { lazy } from "react";
import { Navigate } from 'react-router-dom'
import Layout from '@/components/Layout';
const lazyLoad = (moduleName: string) => {
const Module = lazy(() => import(`@/views/${moduleName}`));
return <Module />;
};
// 路由拦截组件
const Approve = ({ children }: any) => {
const token = sessionStorage.getItem("token");
return token ? children : <Navigate to="/login" />;
};
const routeConfig=[
{
path:"/login",
element:lazyLoad("login"),
auth: false
},
{
path:"/",
element:<Approve><Layout /></Approve>,
auth: false,
children:[
{
path:"/",
element:lazyLoad("home"),
auth: false
},
{
path:"/other",
// element:lazyLoad("other"),
auth: false,
children:[
{
path:"/other/other1",
element:lazyLoad("other"),
auth: false,
},
{
path:"/other/other2",
element:lazyLoad("other"),
auth: false,
}
]
},
{
path:"/mine/:id",
element:lazyLoad("mine"),
auth: false
},
{
path:"/dashboard",
element:lazyLoad("dashboard"),
auth: false
},
]
},
{
path: "*",
element: lazyLoad("not-found"),
},
]
export default routeConfig
3.路由嵌套
Outlet 类似于vue 的router-view,用于路由嵌套
import React,{ FC,useState } from 'react';
import {
MenuFoldOutlined,
MenuUnfoldOutlined,
AndroidOutlined
} from '@ant-design/icons';
import { Outlet } from 'react-router-dom'
import { Layout, theme,Space } from 'antd';
import './Layout.css'
import Menu from '@/components/Menu'
import {menuMode} from '@/const/config'
const { Header, Content, Footer, Sider } = Layout;
const App: FC = () => {
const {
token: { colorBgContainer },
} = theme.useToken();
const [collapsed, setCollapsed] = useState(false);
const [bool,setBool]=useState(menuMode=='horizontal')
return (
<Layout style={{height:'100%'}}>
{bool?<Menu/>:
<Sider
trigger={null} collapsible collapsed={collapsed}
>
<div id="logo"><AndroidOutlined /><span>XXXXXXX系统</span></div>
<Menu/>
</Sider>
}
<Layout className="site-layout">
{bool?'':
<Header style={{ padding: 0,paddingLeft:'20px',textAlign:'left', background: colorBgContainer }}>
<Space>{React.createElement(collapsed ? MenuUnfoldOutlined : MenuFoldOutlined, {
className: 'trigger',
onClick: () => setCollapsed(!collapsed),
})}
</Space>
</Header>
}
<Content style={{ }}>
<div style={{ marginLeft: bool?0:10,marginTop:bool?0:10, minHeight: 360,height:'100%', background: colorBgContainer }}>
<Outlet />
</div>
</Content>
<Footer style={{ textAlign: 'center' }}>Ant Design ©2023 Created by Ant UED</Footer>
</Layout>
</Layout>
)
};
export default App;
4.修改app.tsx
import {useRoutes } from 'react-router-dom';
import './App.css';
import routerConfig from './router/config'
function App() {
const element =useRoutes(routerConfig)
return (
<div className="App">
{element}
</div>
);
}
export default App;
5.修改index.tsx
import React from 'react';
import { Provider } from 'react-redux'
import ReactDOM from 'react-dom/client';
import { BrowserRouter } from 'react-router-dom';
import store from '@/store'
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import Loading from "views/loading";
import './utils/global'
const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement
);
root.render(
<React.StrictMode>
<Provider store={store}>
<BrowserRouter>
<React.Suspense fallback={<Loading />}><App /></React.Suspense>
</BrowserRouter>
</Provider>
</React.StrictMode>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
6.路由跳转和传参
menu.tsx
import React, { useState } from 'react';
import { BankOutlined,GithubOutlined,CiOutlined,AreaChartOutlined } from '@ant-design/icons';
import {useNavigate } from 'react-router-dom'
import type { MenuProps } from 'antd';
import {Menu} from 'antd'
import {menuMode} from '@/const/config'
import './index.less'
const items: MenuProps['items'] = [
{
label: '首页',
key: '/',
icon: <BankOutlined />,
},
{
label: '测试',
key: '/other',
icon: <CiOutlined />,
children:[
{
label: '测试1',
key: '/other/other1',
},
{
label: '测试2',
key: '/other/other2',
},
]
},
{
label: '图表',
key: '/dashboard',
icon: <AreaChartOutlined />,
disabled: false,
children:[
{
label: '测试1',
key: '/other/other1',
},
{
label: '测试2',
key: '/other/other2',
},
]
},
{
label: '我的',
key: '/mine/10?a=10&b=20',
icon: <GithubOutlined />,
},
{
label: (
<a href="https://ant.design" target="_blank" rel="noopener noreferrer">
Navigation Four - Link
</a>
),
key: 'alipay',
},
];
const App: React.FC = () => {
const [current, setCurrent] = useState('/');
const [mode, setMode] = useState(menuMode);
const navigate = useNavigate()
const onClick: MenuProps['onClick'] = (e) => {
console.log('click ', e);
setCurrent(e.key);
navigate(e.key, { state:{name:'jerrry',age:10}, })
};
return <Menu className="mstye" onClick={onClick} selectedKeys={[current]} mode={mode} theme="dark" items={items} />;
};
export default App;
7.几种路由传参总结
import { useLocation,useParams ,useNavigate } from 'react-router-dom'
const navigate = useNavigate()
navigate('/path/', { state:{name:'jerrry',age:10}, })
// 需要动态路由配合 /login/:id/:age
let pp=useParams()
接收到的是{id:10,age:20}
// 可以拿到 state 和 search /path?a=10&b=20
let ap=useLocation()
接收的是路由对象 包含search和state
pathname: "/mine"
search: "?a=10&b=20"
state: {name: 'jerrry', age: 10}
2.axios封装和使用
封装axios
import axios from "axios";
import NProgress from "nprogress";
import { message } from "antd";
import { BASE_URL, TIMEOUT } from "@/const/config";
const instance = axios.create({
baseURL: BASE_URL,
timeout: TIMEOUT,
});
instance.interceptors.request.use(
(config) => {
// 1.发送网络请求时, 在界面的中间位置显示Loading的组件
NProgress.start();
// 2.某一些请求要求用户必须携带token, 如果没有携带, 那么直接跳转到登录页面
// 3.params/data序列化的操作
return config;
},
(err) => {
console.log(err);
}
);
instance.interceptors.response.use(
(res) => {
NProgress.done();
return res.data;
},
(err) => {
if (err && err.response) {
switch (err.response.status) {
case 400:
console.log("请求错误");
break;
case 401:
console.log("未授权访问");
break;
default:
console.log("其他错误信息");
}
}
message.error("当前网络异常,请稍后重试");
NProgress.done();
return err;
}
);
export default instance;
再创建api.ts 在这里写具体的请求,哪里需要就从这里引用
import http from './http'
const api ={
queryList(o:Object){
return http({
url:'/queryList',
method:'get',
params:o
})
}
}
export default api
import api from '@/utils/api'
api.queryList({}).then(res=>{
console.log('----ooo',res)
})