使用react实现后台管理系统项目

您所在的位置:网站首页 无法编辑default_page_url 使用react实现后台管理系统项目

使用react实现后台管理系统项目

2023-03-08 20:21| 来源: 网络整理| 查看: 265

一.开发React必须依赖三个库

    1.react:包含react所必须的核心代码

    2.react-dom:react渲染在不同平台所需要的核心代码

    3.babel:将jsx转换成React代码的工具

二.React的依赖引入

    1.方式一:直接CDN引入

    2.方式二:下载后,添加本地依赖

        1).在html中引入             a.react.js             b.react-dom.js             c.babel.min.js

    3.方式三:通过npm管理(后续脚手架再使用)

三.定义组件化

1.react有两种方式定义组件

    1).采用class类来实现

    2).采用hook(函数)的方式来实现(定义组件首字母要大写,必须要继承React.Component)

    3).函数组件(function)

2.setState内部会做两件事情: 1.将state中的值改掉 2.自动执行render函数渲染页面

3.输出und,原因使用babel来去编译的话,意味着在严格模式下编译,那么在严格模式下得函数内部this指向und,

所以this也是指向und

4.组件化方法

    1).编写React的script代码中,必须添加 type="text/babel",作用是可以让babel解析jsx的语法

    2).使用ReactDOM.createRoot创建一个根节点用变量接收,把内容渲染到root上

        const root = ReactDOM.createRoot(document.querySelector('#root'))

    3).定义组件

        const App

    4).要渲染的根组件

        root.render()

    5).然后再定义class类(定义的组件名必须要大写),继承React.Component

        class App extends React.Component {}

    6).接着步骤5,里面有一个构造函数(子类继承父类)相当于data在构造函数中的state属性,this.state = {定义的数据}

        constructor(){super() this.state = {msg: 'Hello World'}}

    7).接着步骤6,render是渲染函数,相当于vue中的template(模板)         render() {                 return (                                                      {this.state.msg}                                          )             }

this.setState 来更新数据S

四.react项目文件认识

1.node_modules所有的依赖

2.src代码区域

    a.根组件

    b.index.js运行项目的主入口

3.package.json包管理文件

五.JSX(语法糖)

    1.JSX的使用

        1).当变量是Number ,String,Array类型时,可以直接显示。

        2).当变量是null,undefined,boolean时,内容为空。

            若希望显示,则需要转成字符串;

            转换方式:toString,和“”空字符串拼接,String(变量)等方式;

        3).对象类型不能作为子元素(not valid as a React child)

    2.规范

         1) 需要使用()包含,代表一个整体

               2) jsx只能有一个根节点

                3) 可以使用单标签和双标签,单标签需要/结束

    3.jsx绑定属性

         1).绑定普通的属性,直接使用{}绑定                         百度一下

                2).绑定class属性,需要使用className而不是用class来说声明,class被占用了                        

我是p标签里的孩子

                3).绑定动态样式                        

我是p标签里的孩子的孩子

                4).采用数组的方式绑定动态样式active,由于数组会默认以逗号连接, 因此绑定class属性需要调用join方法, 让它们以空格拼接                         

我是p标签里的孩子的孩子的孩子

            5).绑定内联样式                                             return list             }

    7.从redux下创建store文件夹,创建新的文件

        a.引入store

            const store=require('../store')

        b.使用getState获取到定义的数据

             console.log(store.getState())

十六.代理

1.安装:npm install --save-dev http-proxy-middleware

2.在src目录下创建一个setupProxy.js文件,在这个文件中配置

3.创建文件:src/setupProxy.js

const {createProxyMiddleware} =require('http-proxy-middleware')//按需导入 module.exports=function(app){     app.use(         '/api',         createProxyMiddleware({             target:'http://iwenwiki.com:3002',//真实地址,目标服务器             changeOrigin:true,//运行跨越             pathRewrite:{                 '/api':'',//路径重写             }         })     ) }

十七.路由

1.非路由组件:直接添加到父组件里子组件

2.路由组件:通过路由跳转的组件(点击谁就会有切换的效果)

3.路由使用:

    1).下载:npm install --save [email protected] -S

    2).引用 import { HashRouter,BrowserRouter ,Route,Switch,Redirect} from "react-router-dom";

    3).HashRouter/BrowserRouter路由包裹容器

        区别:HashRouter地址栏里带#               BrowserRouter:地址栏里带/

     4).在需要使用路由的地方引入

        import { Route, Routes, Navigate, Link } from "react-router-dom";

    5).使用Routes包裹定义路由走向路由规则          path:匹配路径 element:加载指定          的组件          4.Switch只能匹配一个路由规则

使用BrowserRouter                                    

5.路由重定向(Navigate )

    

    默认路由,使用重定向的方式Navigate导航,后面跟着to属性

6.404页面(配置在路由的最后)

    

7.嵌套路由(路由嵌套路由)

       

        

         

8.使用Link中的to进行跳转

排行榜

    

Outlet相当于路由视图窗口,起到一个占位符作用

9.useNavigate跳转并传值

10.useParams作用:回当前匹配路由的`params`参数

11.useSearchParams  用于读取和修改当前位置的 URL 中的查询字符串

十八.异步组件

1.在index.js中引入import { Suspense } from 'react'

2.使用把App组件包裹起来

使用React.lazy的方式来定义组件,则代表此组件是一个异步组件

3. 将组件改成异步组件使用lazy写法:const 名称 = React.lazy(()=>import('组件路径'))

十九.hook的使用

    1.useState处理之后数据返回的是一个数组

    数组的第一个元素就是定义数据

    数组的第二个元素就是操作数据的函数

   2.useEffect只有组件渲染(render)的操作,那么渲染(render)完之后都会触发hook     函数 第一个参数是一个函数(普通函数,箭头函数) 第二个参数是一个数组,此hook函数所依赖的数据     (只有依赖数据变化的时候函数才会调用)     相当于是挂载后     数据的初始化     只在页面初始化的时候触发一次,不依赖任何数据

redux的四个文件 index.js(store文件夹的主入口) constant.js常量类型(action.type)文件 reduer.js纯函数文件 actionCreator.js(action创建者)

Fragments 空容器不会被渲染Fragments允许你将值列表分组,而无需向DOM添加节点包括空标签容器,不被渲染

编程式导航 配置路由this.props history:路由跳转方式api方法,可以实现路由跳转js location match路由配置信息 包含路由path 路由参数 路由的url地址 this.props.history.goBack返回上一层 this.props.history.push('/path路径)跳转进入某一个路径 有返回功能/path/参数 this.props.history.replace("/path路径")跳转进入某一个路径并关闭当前页面,没有返回功能

1.安装vite+react

2.安装Ant Design组件库

npm install antd --save

3.axios封装

import axios from 'axios'//引入axios const instance = axios.create({ baseURL: '/',//请求路径 timeout: 5000,//请求超时 }); // 添加请求拦截器 instance.interceptors.request.use((config) => { // 在发送请求之前做些什么 config.headers['token'] = sessionStorage.getItem('token') return config; }, function (error) { // 对请求错误做些什么 return Promise.reject(error); }); // 添加响应拦截器 instance.interceptors.response.use((response) => { // 对响应数据做点什么 return response; }, (error) => { // 对响应错误做点什么 return Promise.reject(error); }); export default instance//暴露函数

开启代理

import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' // https://vitejs.dev/config/ export default defineConfig({ plugins: [react()], server: { proxy: { // 本地开发环境通过代理实现跨域,生产环境使用 nginx 转发 // 正则表达式写法 '^/api': { target: 'http://192.168.1.56:8081', // 后端服务实际地址 changeOrigin: true, //开启代理 rewrite: (path) => path.replace(/^\/api/, '') } } } })

login页面(html)

import React from 'react'; import { Button, Form, Input, Card } from 'antd';//引入antd样式组件 import { LockOutlined, UserOutlined } from '@ant-design/icons';//引入antd小图标 import { useNavigate } from "react-router-dom";//路由重定向 import { login } from '../api/login';//引入api封装 import { useDispatch } from "react-redux"; import { logins } from "../store/modules/loginSlice"; const App = () => { const dispatch = useDispatch()//调用dispatch更新数据 const navigate = useNavigate()//路由重定向 const onFinish = (values) => { login({ username: values.username, password: values.password }).then(res => { if (res.data.errmsg == "成功") { // let tokenData=res.data.data.token dispatch(logins(res.data.data.token))//从后台获取到token navigate('/home')//跳转到主页 } }) }; const onFinishFailed = (errorInfo) => { console.log('Failed:', errorInfo); }; return ( // onFinish 提交表单且数据验证成功后回调事件 initialValues 表单默认值,只有初始化以及重置时生效 // onFinishFailed 提交表单且数据验证失败后回调事件 { span: 5, }} wrapperCol={{ span: 16, }} initialValues={{ remember: true, }} onFinish={onFinish} onFinishFailed={onFinishFailed} > { ...store }}> , )

效果图如下:

 home页面

import React, { useEffect, useState } from 'react'; import { Layout, Input, Button, Pagination, notification, Table, Modal, Form, Menu, theme, Breadcrumb } from 'antd';//样式 import { SearchOutlined, ArrowDownOutlined, CheckOutlined, SmileOutlined, MenuFoldOutlined, MenuUnfoldOutlined, UploadOutlined, UserOutlined, VideoCameraOutlined, } from '@ant-design/icons';//按钮图标样式 const { Header, Footer, Content, Sider } = Layout;//布局容器 const { TextArea } = Input; import { lists, deletes, creates, updates } from '../api/home';//api封装 const App = () => { const columns = [ { title: '问题ID', align: 'center',//居中 dataIndex: 'id', }, { title: '问题内容', align: 'center', dataIndex: 'answer',//列表数据 render: (text, row, index) => {//render 生成复杂数据的渲染函数,参数分别为 text当前行的值,row当前行数据,index行索引 return ( {/* 当前bool为false显示span标签里面的数据 input标签中value显示输入框的数据 onChange输入框内容变化时的回调*/} {row.bool ? { editsData.answer = e.currentTarget.value; setEdit({ ...editsData }) }} /> : {row.answer}} ) } }, { title: '问题回复', align: 'center', dataIndex: 'question', render: (text, row, index) => { return ( {row.bool ? { editsData.question = e.target.value; setEdit({ ...editsData }) }} /> : {row.question}} ) } }, { title: '操作', align: 'center', render: (text, row, index) => { return ( { !row.bool ? ( edits(row)}>编辑 deleteData(row)}>删除 ) : ( determines(editsData)}>确定 cancels()}>取消 ) } ) } }, ]; // 渲染列表 const [total, setTotal] = useState(0)//总条数 const [page, setPage] = useState(1)//当前显示的页数 const [limit, setLimit] = useState(10)//当前显示的条数 let [listData, setlist] = useState([])//渲染列表 const general = () => { lists(page, limit).then(res => { let listData = res.data.data.list//获取列表数据赋值给声明的变量 listData = listData.map((item) => ({ ...item, bool: false }))//获取到的给数组中每个对象添加一个bool属性 const total = res.data.data.total//获取到总条数数据赋值给声明的变量 setlist(listData)//获取到的列表数据进行操作 setTotal(total)//获取到的总条数数据进行操作 }) } // 初始化显示列表 useEffect(() => { general() }, [page, limit]) // 分页 const onChange = (pages, pageSize) => { setPage(pages)//对当前显示的页数进行数据操作 setLimit(pageSize)//对当前显示的条数进行数据操作 } const onShowSizeChange = (current, size) => { // console.log(current,8888) } // 添加确定按钮 const [form] = Form.useForm();//用于表单验证 // 经 Form.useForm() 创建的 form 控制实例,不提供时会自动创建 const [isModalOpen, setIsModalOpen] = useState(false);//添加弹框显示隐藏 // 添加 const onFinish = (value) => { creates({ answer: value.answer, question: value.question }).then(res => { if (res.data.errmsg == '成功') { notification.open({ message: '成功', description: '添加成功', icon: ({ color: '#108ee9', }} />), }); general(); } }) } // 编辑取消 const cancels = () => { general();//调用渲染方法 } // 删除 const deleteData = (row) => { deletes(row).then(res => { if (res.data.errmsg == '成功') { notification.open({ message: '成功', description: '删除成功', icon: ({ padding: 0, background: colorBgContainer, }}> {React.createElement(collapsed ? MenuUnfoldOutlined : MenuFoldOutlined, { className: 'trigger', onClick: () => setCollapsed(!collapsed), })} 首页 关键词 通用问题 { width: '200px', margin: '0px 10px' }} /> 查找 showModal()}>添加 导出 {/*open对话框是否可见 footer底部内容,当不需要默认底部按钮时添加弹框 destroyOnClose清除弹框内容 onCancel点击遮罩层或右上角叉或取消按钮的回调*/} { span: 16 }} form={form} onFinish={onFinish} onFinishFailed={onFinishFailed} autoComplete="off">


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3