当前位置:   article > 正文

React项目实战步骤(后台系统)_npm创建后台react项目

npm创建后台react项目

一、项目起步

1.创建项目

$ npx create-react-app my_react

2、安装依赖

本项目用到的依赖可以预先安装好:

  • antd
  • redux与react-redux
  • react-router-dom
  • axios
$ npm i antd redux react-redux react-router-dom@6 axios --save

3.配置路由 (根据项目分析需要几个页面,以及页面之间的关系)

  1. /*
  2. App > List + Edit + Means
  3. Login
  4. Register
  5. History模式 -- BrowserRouter
  6. Hash模式 -- HashRouter
  7. */
  8. import App from '../App'
  9. import Edit from '../pages/Edit'
  10. import List from '../pages/List'
  11. import Means from '../pages/Means'
  12. import Login from '../pages/Login'
  13. import Register from '../pages/Register'
  14. import {BrowserRouter as Router, Routes, Route} from 'react-router-dom'
  15. const BaseRouter = () => (
  16. <Router>
  17. <Routes>
  18. <Route path='/' element={<App />}>
  19. <Route path='/edit' element={<Edit />}></Route>
  20. <Route path='/list' element={<List />}></Route>
  21. <Route path='/means' element={<Means />}></Route>
  22. </Route>
  23. <Route path='/login' element={<Login />}></Route>
  24. <Route path='/register' element={<Register />}></Route>
  25. </Routes>
  26. </Router>
  27. )
  28. export default BaseRouter

或者也可以写成这样(与·vue写法相似)

  1. import App from '../App'
  2. import Edit from '../pages/Edit'
  3. import List from '../pages/List'
  4. import Means from '../pages/Means'
  5. import Login from '../pages/Login'
  6. import Register from '../pages/Register'
  7. import {Navigate} from 'react-router-dom'
  8. export default [
  9. { path:'/',
  10. element:<App />,
  11. children[
  12. {
  13. path:'edit',
  14. element:<Edit />
  15. },
  16. {
  17. path:'list',
  18. element:<List/>
  19. },
  20. {
  21. path:'means',
  22. element:<Means />
  23. }
  24. ]
  25. },
  26. {
  27. path:'/login',
  28. element:<Login />
  29. },
  30. {
  31. path:'/register',
  32. element:<Register />
  33. }
  34. ]

4.确认使用框架,编写静态代码

UI框架使用:Ant Design

在入口文件index.js中:

  1. import ReactDOM from 'react-dom'
  2. import App from './App'
  3. import 'antd/dist/antd.css';
  4. ReactDOM.render(
  5. <App />,
  6. document.getElementById('root')
  7. )

然后在App.jsx中:

  1. import React from 'react'
  2. import { Button } from 'antd';
  3. export default function App() {
  4. return (
  5. <div>
  6. <Button type="primary">Primary Button</Button>
  7. </div>
  8. )
  9. }

如果可以看到这款颜色的按钮,即代表使用成功:

二、Request封装

1.在src下创建request目录,并在其中创建request.js及api.js

2.封装axios请求

(导入axios,定义并创建域名接口,然后共享全局变量)

request.js:

  1. import axios from 'axios'
  2. // 配置项
  3. const axiosOption = {
  4. baseURL: '域名' ,// 请求接口的域名
  5. timeout: 5000
  6. }
  7. // 创建一个单例
  8. const instance = axios.create(axiosOption);
  9. // 添加请求拦截器
  10. instance.interceptors.request.use(function (config) {
  11. let token = localStorage.getItem('cms-token')
  12. if(token){
  13. config.headers = {
  14. 'cms-token':window.localStorage.getItem('cms-token')
  15. }
  16. }
  17. return config;
  18. }, function (error) {
  19. // 对请求错误做些什么
  20. return Promise.reject(error);
  21. });
  22. // 添加响应拦截器
  23. instance.interceptors.response.use(function (response) {
  24. // 对响应数据做点什么
  25. return response.data;
  26. }, function (error) {
  27. // 对响应错误做点什么
  28. return Promise.reject(error);
  29. });
  30. export default instance;

3.api.js

指API接口,在此之前需要导入request文件在获取时候可以传入接口参数,get方法获取则定义为params方法,post方法则定义data方法

  1. import request from './request'
  2. export const getNewsAPI = function (接口参数) {
  3. return request.get('接口的api', { params: { 接口参数 } }) // 多个参数用逗号隔开
  4. }

4.在组件使用 

  1. methods: {
  2. async initArticleList () {
  3. const { data: res } = await getNewsAPI(与组件对接的参数) // 在此可以在组件中定义好参数方便存储
  4. console.log(res.data)
  5. }

4.解决跨域

在  react 17.x中 

方法一:我们可以在package.json 中写

"proxy":{"这里写你要请求的地址"}

方案二(推荐):

先安装 http-proxy-middleware :

  1. npm install http-proxy-middleware
  2. 或者
  3. yarn add http-proxy-middleware

这里注意,http-proxy-middleware 模块是有版本区别的,默认安装最新版本,然后在 src 目录下新建 setupProxy.js :

  1. const proxy = require('http-proxy-middleware');
  2. // 这个玩意不用下,react里自己带了
  3. module.exports = function(app) {
  4. app.use(
  5. proxy('/api1', { // 发送请求的时候 react会自动去找这个api1,匹配这个路径,然后去发送对的请求
  6. target: 'http://localhost:5000',
  7. changeOrigin: true, //控制服务器接收到的请求头中host字段的值
  8. pathRewrite: {'^/api1': ''} // 跟上面匹配,这个api1只是找这个路径用的,实际接口中没有api1,所以找个目标地址后,要把api1给替换成空
  9. }),
  10. // changeOrigin设置为true时,服务器收到的请求头中的host为:localhost:5000
  11. // changeOrigin设置为false时,服务器收到的请求头中的host为:localhost:3000
  12. // 注意!!注意!!注意!! changeOrigin默认值为false,需要我们自己动手把changeOrigin值设为true
  13. proxy('/api2', {
  14. target: 'http://localhost:5001',
  15. changeOrigin: true,
  16. pathRewrite: {'^/api2': ''}
  17. }),
  18. )
  19. }

在react18中

  1. const { createProxyMiddleware } = require('http-proxy-middleware')
  2. module.exports = function (app) {
  3. app.use(
  4. createProxyMiddleware('/api1', {
  5. target: 'http://localhost:5000',
  6. changeOrigin: true,
  7. pathRewrite: { '^/api1': '' }
  8. }),
  9. createProxyMiddleware('/api2', {
  10. target: 'http://localhost:5001',
  11. changeOrigin: true,
  12. pathRewrite: { '^/api2': '' }
  13. }),
  14. )
  15. }

或者,还有另一种方法

如果你已经进行了 npm run eject(会复制所有依赖文件和相应的依赖(webpack、babel等)到你的项目。是个单向的操作,一旦 eject ,npm run eject的操作是不可逆的) ,建议你直接修改 config>webpackDevServer.config.js :

  1. proxy: {
  2. '/api': {
  3. target: 'http://47.93.114.103:6688/manage', // 后台服务地址以及端口号
  4. changeOrigin: true, //是否跨域
  5. pathRewrite: { '^/api': '/' }
  6. }
  7. }

然后修改request.js:

  1. const axiosOption = {
  2. baseURL: '/api',
  3. timeout: 5000
  4. }

最后重新执行 npm run start

三.登陆页面重要逻辑部分(注册也一样)

Login.jsx:

  1. import { Link, useNavigate} from 'react-router-dom'
  2. //引入接口
  3. import {LoginApi} from '../axios/api'
  4. export default function Login() {
  5. const navigate = useNavigate()
  6. const onFinish = (values) => {
  7. // console.log('Success:', values);
  8. //使用APi请求数据
  9. LoginApi({
  10. username:values.username,
  11. password:values.password
  12. }).then(res=>{
  13. console.log(res);
  14. if(res.errCode===0){
  15. message.success('登陆成功');
  16. //存储数据(这里需要根据后端返回值来写)
  17. localStorage.setItem('avatar',res.data.avatar)
  18. localStorage.setItem('cms-token',res.data['cms-token'])
  19. localStorage.setItem('editable',res.data.editable)
  20. localStorage.setItem('player',res.data.player)
  21. localStorage.setItem('username',res.data.username)
  22. //跳转路径
  23. navigate('/')
  24. }else{
  25. message.error('用户已存在');
  26. }
  27. })
  28. };

四、路由跳转

使用useNavigate这个路由hook,可以实现路由跳转。若要判断这个路径如果为/,则自动跳转到/home,代码如下:

  1. import React, {useEffect} from 'react'
  2. import {Outlet, Link, useLocation, useNavigate} from 'react-router-dom'
  3. function App() {
  4. let {pathname} = useLocation()
  5. const navigate = useNavigate()
  6. useEffect(()=>{
  7. if(pathname==='/'){
  8. navigate('/home')
  9. }
  10. }, [])
  11. return ...
  12. }
  13. export default App

五、useLocation

使用useLocation这个路由hook,可以获取地址栏路径:

  1. import {useLocation} from 'react-router-dom'
  2. function App() {
  3. let {pathname} = useLocation() // 得到当前路径
  4. }

六、参数携带

1、url子路由形式

通过在路由中配置子路由形式,可以实现参数传递。如给/list携带参数,以这个形式:/list/123。

  1. // 路由文件
  2. <Route path='/list/:id' element={<List />}></Route>
  3. // App.jsx中
  4. <li><Link to="/list/123">列表页</Link></li>

如果想要获取参数的值,可以使用useParams这个路由hook:

  1. import React from 'react'
  2. import {useParams} from 'react-router-dom'
  3. export default function List() {
  4. const params = useParams()
  5. console.log(params) // {id: '123'}
  6. return <h2>List列表页</h2>
  7. }

2、问号?形式

地址栏携带参数还可以通过问号形式:

<li><Link to="/detail?id=456">详情页</Link></li>

获取该参数的方式,需要使用useSearchParams这个路由hook,并且调用getAll方法才能获取得到:

  1. import React from 'react'
  2. import {useSearchParams} from 'react-router-dom'
  3. export default function Detail() {
  4. const [params] = useSearchParams()
  5. console.log(params.getAll('id')) // ['456']
  6. return <h2>Detail详情页</h2>
  7. }

3、state携带

以上两种携带参数的方式,都只能携带简单的参数,如果数据量较大,其实并不方便,因此,在使用useNavigate()这个hook实现跳转时,其实也可以携带参数:

  1. navigate('/home', {
  2. state: {id: 789}
  3. })

获取该参数的方式便是使用useLocation这个路由hook:

七、分页步骤

1.antd组件table内置了分页效果

  1. return (
  2. <div className='list_table'>
  3. <Table
  4. showHeader={false}
  5. columns={columns}
  6. dataSource={arr}
  7. onChange={pageChange} //分页函数
  8. //分页效果pagination值是动态可操作的所以用useState来管理
  9. pagination={pagination}
  10. />
  11. </div>
  12. )
  1. const [pagination, setPagination] = useState({ current: 1, pageSize: 10, total: 0 })
  2. //current、pageSize、total这三项是需要做配置的

配置完成以后,当点击下一页的时候,就可以得到那三个参数最新的值

const pageChange = (arg) => getArticleList(arg.current, arg.pageSize);

然后再一次的做请求,通过setPagination修改 useState里面的值

  1. // 提取请求的代码
  2. const getArticleList = (current, pageSize) => {
  3. ArticleListApi({
  4. num: current,
  5. count: pageSize
  6. }).then(res => {
  7. if (res.errCode === 0) {
  8. // 更改pagination
  9. let { num, count, total } = res.data;
  10. setPagination({ current: num, pageSize: count, total })
  11. // 深拷贝获取到的数组
  12. let newArr = JSON.parse(JSON.stringify(res.data.arr));
  13. // 声明一个空数组
  14. let myarr = []
  15. /*
  16. 1. 要给每个数组项加key,让key=id
  17. 2. 需要有一套标签结构,赋予一个属性
  18. */
  19. newArr.map(item => {
  20. let obj = {
  21. key: item.id,
  22. date: moment(item.date).format("YYYY-MM-DD hh:mm:ss"),
  23. mytitle: <MyTitle id={item.id} title={item.title} subTitle={item.subTitle} />
  24. }
  25. myarr.push(obj)
  26. })
  27. setArr(myarr)
  28. }
  29. })
  30. }

 上面这一行就是再次请求

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/475108
推荐阅读
相关标签
  

闽ICP备14008679号