# react-antd **Repository Path**: lt199934/react-antd ## Basic Information - **Project Name**: react-antd - **Description**: react+antd 后台管理快速开发模板 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2023-05-08 - **Last Updated**: 2023-12-04 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Getting Started with Create React App This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). ## Available Scripts In the project directory, you can run: ### `npm start` Runs the app in the development mode.\ Open [http://localhost:3000](http://localhost:3000) to view it in the browser. The page will reload if you make edits.\ You will also see any lint errors in the console. ### `npm test` Launches the test runner in the interactive watch mode.\ See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. ### `npm run build` Builds the app for production to the `build` folder.\ It correctly bundles React in production mode and optimizes the build for the best performance. The build is minified and the filenames include the hashes.\ Your app is ready to be deployed! See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. ### `npm run eject` **Note: this is a one-way operation. Once you `eject`, you can’t go back!** If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own. You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it. ## 一,通过create-react-app脚手架创建项目 安装脚手架 ``` npm install -g create-react-app ``` ![创建项目](images/react-0.png) 安装yarn包管理器 `npm install -g yarn` 创建项目 `npx create-react-app my-app --template typescript` 如图我们就已经搭建好了一个react项目雏形 ​快速启动项目,运行 ``` cd my-app npm start 或 yarn start ``` ![npm run start](images/react-1.png) ## 二,引入Antd yarn add antd ## 三,快速搭建后台模板 打开antd官网:Ant Design - 一套企业级 UI 设计语言和 React 组件库 配置App.tsx ``` import './App.css'; import React, {useState} from 'react'; import { DesktopOutlined, FileOutlined, MenuFoldOutlined, MenuUnfoldOutlined, PieChartOutlined, TeamOutlined, UserOutlined, } from '@ant-design/icons'; import type {MenuProps} from 'antd'; import {Button, Breadcrumb, Layout, Menu, theme} from 'antd'; import {Link} from "react-router-dom"; import {renderRoutes} from "react-router-config"; import routes from "./router/index"; const {Header, Content, Footer, Sider} = Layout; type MenuItem = Required['items'][number]; function getItem( label: React.ReactNode, key: React.Key, icon?: React.ReactNode, children?: MenuItem[], ): MenuItem { return { key, icon, children, label, } as MenuItem; } const items: MenuItem[] = [ getItem(主页, '1', ), getItem(用户管理, '2', ), getItem('文章管理', 'sub1', , [ getItem(所有文章, '3'), getItem('Bill', '4'), getItem('Alex', '5'), ]), getItem('Team', 'sub2', , [getItem('Team 1', '6'), getItem('Team 2', '8')]), getItem('Files', '9', ), ]; const App: React.FC = () => { const [collapsed, setCollapsed] = useState(false); const { token: {colorBgContainer}, } = theme.useToken(); return ( setCollapsed(value)}>
React-Antd-Admin
Home, }, { title: 'User', } ]} style={{margin: '16px 0'}}/>
{renderRoutes(routes)}
Ant Design ©2023 Created by Ant UED
); }; export default App; ``` ![主框架layout](images/react-2.png) ## 四,配置路由 ``` yarn add react-router-dom@5.2.0 yarn add react-router-config yarn add @types/react-router-config yarn add @types/react-router-dom yarn add react-router@5.2.0 -S ``` router/index.ts ``` import { lazy } from 'react' const routes = [ { path:"/article", component: lazy(()=>import('../views/Article')), meta: { title:"文章管理", }, exact: true, routes: [] }, { path:"/user", component: lazy(()=>import('../views/user/index')), meta: { title:"用户管理", }, child: [] }, { path:"/", component: lazy(()=>import('../views/Home')), meta: { title:"App", }, child: [] }, ] export default routes; ``` index.tsx ``` import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css'; import App from './App'; import reportWebVitals from './reportWebVitals'; import { HashRouter as Router } from "react-router-dom" const root = ReactDOM.createRoot( document.getElementById('root') as HTMLElement ); root.render( ); // 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(); ``` 创建路由组件 views/user/index.tsx ``` import React, {useState} from 'react'; import {Button, Form, Input, Modal, Pagination, Space, Table, Tag} from 'antd'; import type {ColumnsType} from 'antd/es/table'; import {DeleteOutlined, EditOutlined,SearchOutlined} from '@ant-design/icons'; import UserForm from "./components/UserForm"; interface DataType { key: string; name: string; age: number; address: string; tags: string[]; } const rowSelection = { onChange: (selectedRowKeys: React.Key[], selectedRows: DataType[]) => { console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows); }, getCheckboxProps: (record: DataType) => ({ disabled: record.name === 'Disabled Index', // Column configuration not to be checked name: record.name, }), }; const data: DataType[] = [ { key: '1', name: 'John Brown', age: 32, address: 'New York No. 1 Lake Park', tags: ['nice', 'developer'], }, { key: '2', name: 'Jim Green', age: 42, address: 'London No. 1 Lake Park', tags: ['loser'], }, { key: '3', name: 'Joe Black', age: 32, address: 'Sydney No. 1 Lake Park', tags: ['cool', 'teacher'], }, { key: '4', name: 'John Brown', age: 32, address: 'New York No. 1 Lake Park', tags: ['nice', 'developer'], }, { key: '5', name: 'Jim Green', age: 42, address: 'London No. 1 Lake Park', tags: ['loser'], }, { key: '6', name: 'Joe Black', age: 32, address: 'Sydney No. 1 Lake Park', tags: ['cool', 'teacher'], }, ]; const Index: React.FC = () => { const [open, setOpen] = useState(false); const [title, setTile] = useState(); const [rowData, setRow] = useState(null); const [confirmLoading, setConfirmLoading] = useState(false); const showModal = (title: String, record: any) => { setRow(record); setTile(title); setOpen(true); }; const handleOk = () => { setConfirmLoading(true); setTimeout(() => { setOpen(false); setConfirmLoading(false); }, 2000); }; const handleCancel = () => { console.log('Clicked cancel button'); setOpen(false); }; const onFinish = (values: any) => { console.log('Success:', values); }; const onFinishFailed = (errorInfo: any) => { console.log('Failed:', errorInfo); }; const columns: ColumnsType = [ { title: 'Name', dataIndex: 'name', key: 'name', render: (text: String) => {text}, }, { title: 'Age', dataIndex: 'age', key: 'age', }, { title: 'Address', dataIndex: 'address', key: 'address', }, { title: 'Tags', key: 'tags', dataIndex: 'tags', render: (tags: string[]) => ( {tags.map((tag) => { let color = tag.length > 5 ? 'geekblue' : 'green'; if (tag === 'loser') { color = 'volcano'; } return ( {tag.toUpperCase()} ); })} ), }, { title: 'Action', key: 'action', render: (_, record) => ( ), }, ]; return (
`总共 ${total} 条`} /> ); }; export default Index; ``` 弹出窗组件 views/user/components/UserForm.tsx ``` import React, {useState} from 'react'; import {Button, Modal, Form, Input, InputNumber} from 'antd'; import {DeleteOutlined, EditOutlined} from '@ant-design/icons'; const UserForm: React.FC = (props) => { // console.log(props) const {title,open,rowData,handleOk,onFinish,onFinishFailed,handleCancel,confirmLoading,}= props; const [form] = Form.useForm(); form.resetFields(); if(title==='修改'){ form.setFieldsValue(rowData); } console.log(form) return (
); }; export default UserForm; ``` ![table页面](images/react-3.png) ![编辑](images/react-4.png) ![新增](images/react-5.png) ## 五,配置less 暴露配置项 `yarn eject` 安装less和less-loader ` yarn add less less-loader -S` 配置webpack.config.js,在 //style files regexes 最下面配置less ``` // less const lessRegex = /\.less$/; const lessModuleRegex = /\.module\.less$/; ``` 在大约530行左右配置 ``` // less { test: lessRegex, exclude: lessModuleRegex, use: getStyleLoaders( { importLoaders: 2, sourceMap: isEnvProduction && shouldUseSourceMap, }, 'less-loader' ), sideEffects: true, }, // less { test: lessModuleRegex, use: getStyleLoaders( { importLoaders: 2, sourceMap: isEnvProduction && shouldUseSourceMap, modules: true, getLocalIdent: getCSSModuleLocalIdent, }, 'less-loader' ), }, ``` 如何创建index.less 和index.scss并引用,重新启动项目 如果出现 如果 Failed to complie,就重新安装一下即可 `yarn add sass -s` ## 六,配置axios和反向代理 安装axios 和 http-proxy-middleware `yarn add axios http-proxy-middleware -s` 在config下创建 setupProxy.js ``` const {createProxyMiddleware} = require('http-proxy-middleware'); module.exports = function(app) { app.use('/api', createProxyMiddleware({ target: 'http://localhost:8080/',//后台服务器地址 changeOrigin: true, pathRewrite: { '^/api': '', },})) } ``` 然后修改 config下 path.js的相关配置 ![输入图片说明](images/react-6.png) 配置 封装 /http/request.ts ``` import axios from "axios" // 创建axios 赋值给常量service const service = axios.create({ baseURL: '/api', timeout: 5000, headers: {//请求头 "Content-Type": "application/json;charset=UTF-8", // "Content-Type": "application/x-www-form-urlencoded;charset=utf-8", "token": null, } }); // 添加请求拦截器(Interceptors) service.interceptors.request.use(function (config) { // 发送请求之前做写什么 let token = localStorage.getItem("token"); // 如果有token if(token){ // 将token放在请求头 config.headers.authorization = token; } return config; }, function (error) { // 请求错误的回调 return Promise.reject(error); }); // 添加响应拦截器 service.interceptors.response.use(function (response) { // 对响应数据做点什么 return response; }, function (error) { // 响应错误的回调 return Promise.reject(error); }); export default service ``` 配置 /http/index.ts ``` import service from "./request"; // 这个模块封装各种请求方式(如:get,post等等) export function post(url: any, params: {}) { return new Promise(function (resovle, reject) { service.post(url, params) .then((res: any) => { if (!res.data) { resovle(res); } resovle(res.data); }, (err: any) => { reject(err); }) .catch((err: any) => { reject(err); }); }); } export function get(url: String, params: []) { let querystr = ""; for (let key in params) { if (params[key]) { querystr += `${key}=${params[key]}&` } } return new Promise(function (resovle, reject) { service.get(url + "?" + querystr) .then((res: any) => { if (!res.data) { resovle(res); } resovle(res.data); }, (err: any) => { reject(err); }) .catch((err: any) => { reject(err); }); }); } ``` 请求api 封装 /api/user.ts ``` //index.ts import Service from "../http/request" //获取所有用户 export function getUserList(config:any) { const params = new URLSearchParams() params.append("pageNum", config.pageNum) params.append("pageSize", config.pageSize) return Service({ url: "/user/page", data: params, }) } ``` 调用服务 ``` getUserList(page).then((res: any) => { setUsers(res); setPage({pageNum: res.pageNum, pageSize: res.pageSize}); }) ``` ## 结尾 到这里我们的React+antd+axios+router的学习就就结束了,欢迎分享给有需要的小伙伴!!! ## 原文地址 [文章地址](https://ltbk.net/front/react/article/1467.html) ## 效果图 ## Learn More You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). To learn React, check out the [React documentation](https://reactjs.org/).