react实现列表增删改查的小demo(class组件版)
前言
react的语法上就是比vue麻烦不少,既然要开手动挡,那就开吧,一个基础的demo
效果图
列表

新增弹窗

编辑弹框

新增一条数据后的效果

代码
根组件 index.jsx
import React, { Component,createRef} from 'react'
import withRouter from '../../utils/withRouter'
import GlobalFormCom from './globalForm'
import GlobalTable from './globalTable'
import './index.less'
import { cloneDeep } from 'lodash'
import { Input, Select , Button , Modal } from 'antd';
import PubSub from 'pubsub-js'export default withRouter(class index extends Component {state = {searchForm:{searchName:'王惊涛',selectValue:'jsCoder'},modalInfo:{isModalOpen:false,modalTitle:'新建数据',},doneType:'add',addFormData:{},editFormData:{},editRecord:{}}searchDom = {width: '200px',marginRight:'16px'}selectOptions = [{label:'前端',value:'jsCoder'},{label:'后端',value:'pythonCoder'}]changeNameInput = (e,name) => {this.setValue('searchForm',this.state.searchForm,name,e.target.value)}changeSelectValue = (e,name) =>{this.setValue('searchForm',this.state.searchForm,name,e)}setValue = (name,data,key,value,fn)=>{let _data = cloneDeep(data)_data[key] = valuethis.setState({[name]:_data},()=>{if(fn){fn()}})}openModal = (flag) =>{this.setState({doneType:flag})let fn = ()=>{this.setValue('modalInfo',this.state.modalInfo,'modalTitle','新建数据')}this.setValue('modalInfo',this.state.modalInfo,'isModalOpen',true,fn)}editHandler = (editData)=>{this.setState({doneType:'edit'},()=>{this.setValue('modalInfo',this.state.modalInfo,'modalTitle','编辑数据')})let data = cloneDeep(editData)this.setState({editRecord:data})this.setValue('modalInfo',this.state.modalInfo,'isModalOpen',true,()=>{setTimeout(()=>{PubSub.publish('editForm',this.state.editRecord)})})}handleOk = ()=>{// this.handleCancel()if(this.state.doneType === 'add'){PubSub.publish('getFormData','add')}else if(this.state.doneType === 'edit'){PubSub.publish('getFormData','edit')}}handleCancel = ()=>{let fn = ()=>{}this.setValue('modalInfo',this.state.modalInfo,'isModalOpen',false,fn)}globalFormStyle = ()=>{if(this.state.isModalOpen === false){return {display:none}}}sendFormData = (formData,flag)=>{if(flag === 'add'){this.setState({addFormData:formData},()=>{PubSub.publish('addTableData',this.state.addFormData)})}else if(flag === 'edit'){this.setState({editFormData:formData},()=>{PubSub.publish('editTableData',this.state.editFormData)})}}reqList = ()=>{setTimeout(()=>{PubSub.publish('reqList')})}render() {return (<div className='content'><div className='topSearch'><span className='labelSpan'>姓名:</span><Input placeholder="输入姓名" onChange={(e)=>this.changeNameInput(e,'searchName')} value={this.state.searchForm.searchName} style={this.searchDom} /><span className='labelSpan'>类型:</span><SelectdefaultValue={this.state.searchForm.selectValue}style={this.searchDom}allowClearoptions={this.selectOptions}onChange={(e)=>this.changeSelectValue(e,'selectValue')}/><Button type='primary' onClick={this.reqList}>数据重置</Button><Button type='primary' className='addBtn' onClick={()=>this.openModal('add')}>新增</Button></div><div className='tableBox'><GlobalTable addFormData={this.state.addFormData} closeModal={this.handleCancel} editHandler={this.editHandler}></GlobalTable></div><div className='footer'></div><Modal title={this.state.modalInfo.modalTitle} open={this.state.modalInfo.isModalOpen} onOk={this.handleOk} onCancel={this.handleCancel} width="800px" okText="确定" cancelText="取消" destroyOnClose><GlobalFormCom sendFormData={this.sendFormData}></GlobalFormCom></Modal></div>)}
})
表格组件 globalTable.jsx
import React, { Component } from 'react'
import withRouter from '../../utils/withRouter'
import { Table, Tag, Space, Button } from 'antd';
const { Column, ColumnGroup } = Table;
import PubSub from 'pubsub-js';
import { cloneDeep } from 'lodash';
export default withRouter(class globalTable extends Component {state = {data: []}genderMap = {man: '男',woman: '女'}workMap = {pythonCoder: '后端',jsCoder: '前端'}componentDidMount() {this.reqList()PubSub.unsubscribe('addTableData')PubSub.subscribe('addTableData',(msg,data)=>{this.setTableHandler(data,'add')})PubSub.unsubscribe('editTableData')PubSub.subscribe('editTableData',(msg,data)=>{this.changeTableRow(data)})PubSub.unsubscribe('reqList')PubSub.subscribe('reqList',()=>{this.reqList()})}changeTableRow = (rowData)=>{let cloneTableData = cloneDeep(this.state.data)let index = cloneTableData.findIndex(val=>val.name === rowData.name)cloneTableData[index] = rowDatathis.setState({data:cloneTableData})this.props['closeModal']()}setTableHandler = (data,type)=>{let tableData = cloneDeep(this.state.data)if(type === 'add'){tableData.push(data)this.setState({data:tableData},()=>{this.props['closeModal']()})}}actionBtn = {marginRight:'12px'}editHandler =(record)=>{this.props.editHandler(record)}deleteHandler = (record)=>{let index = this.state.data.findIndex(item=>item.name === record.name)if(index !== -1){let tableData = cloneDeep(this.state.data)tableData.splice(index,1)this.setState({data:tableData})}}reqList = ()=>{this.setState({data:[{name: '马师',gender: 'woman',work: 'jsCoder',birthDate: '1995-01-04',desc: '描述文字'}]})}render() {return (<div><Table dataSource={this.state.data} rowKey="name" pagination={false}><Column title="姓名" dataIndex="name" key="name" width={120}></Column><Column title="性别" dataIndex="gender" key="gender" width={80} render={(text, record) => {return <span>{this.genderMap[text]}</span>}}></Column><Column title="工作" dataIndex="work" key="work" width={200} render={(text => (<span>{this.workMap[text]}</span>))}></Column><Column title="出生日期" dataIndex="birthDate" key="birthDate" width={200}></Column><Column title="描述" dataIndex="desc" key="desc"></Column><Column title="操作" key="action" width={280} render={(text,record) => (<div><Button type='primary' style={this.actionBtn} onClick={()=>this.editHandler(record)} >编辑</Button><Button style={this.actionBtn} onClick={()=>this.deleteHandler(record)}>删除</Button></div>)}></Column></Table></div>)}
})
表单组件 globalForm.jsx
import React, { Component, forwardRef, createRef } from 'react'
import withRouter from '../../utils/withRouter'
import { InboxOutlined, UploadOutlined } from '@ant-design/icons';
import PubSub from 'pubsub-js';
import {Input,Form,Radio,Select,DatePicker
} from 'antd';
import dayjs from 'dayjs';
const { Option } = Select;
const { TextArea } = Input;
const formItemLayout = {labelCol: {span: 6,},wrapperCol: {span: 14,},
};
const normFile = (e) => {if (Array.isArray(e)) {return e;}return e?.fileList;
};
const onFinish = (values) => {
};const GlobalForm = withRouter(class index extends Component {state = {formData: {name: '',gender: true,work: null,desc: '',birthDate: null,}}workList = [{label: '前端',value: 'jsCoder'},{label: '后端',value: 'pythonCoder'}]changeFormItem = (e, name) => {switch (name) {case 'work':this.setFormValue(e, name)case 'birthDate':this.setFormValue(e, name)breakdefault:this.setFormValue(e.target.value, name)}}setFormValue = (value, key, fn) => {let _formData = this.state.formData_formData[key] = valuethis.setState({ formData: _formData }, () => {if (fn) {fn()}})}changeDate = (date, dateString) => {this.setFormValue(dateString, 'birthDate')}componentDidMount() {PubSub.unsubscribe('getFormData')PubSub.subscribe('getFormData', (msg, data) => {if (data === 'add') {this.formRef.current.validateFields().then((value) => {this.props.sendFormData(this.state.formData, 'add')}).catch((error) => {})} else if (data === 'edit') {this.formRef.current.validateFields().then((value) => {this.props.sendFormData(this.state.formData, 'edit')}).catch((error) => {})}})PubSub.unsubscribe('editForm')PubSub.subscribe('editForm', (msg, data) => {data.birthDate = dayjs(data.birthDate)this.setState({ formData: data }, () => {for (let item in data) {this.formRef.current.setFieldValue(item, data[item])}})})}componentDidUpdate() {}componentWillUnmount() {PubSub.unsubscribe('getFormData')PubSub.unsubscribe('editForm')}formRef = createRef()render() {return (<div><Formref={this.formRef}name="validate_other"{...formItemLayout}onFinish={onFinish}initialValues={this.state.formData}style={{maxWidth: 600,}}><Form.Itemname="name"label="姓名"hasFeedbackrules={[{required: true,message: '请输入名字',},]}><Input placeholder="请输入姓名" onChange={(e) => this.changeFormItem(e, 'name')} value={this.state.formData.name}></Input></Form.Item><Form.Item name="gender" label="性别" rules={[{required: true,message: '请选择性别',},]}><Radio.Group value={this.state.formData.gender} onChange={(e) => this.changeFormItem(e, 'gender')}><Radio value="man">男</Radio><Radio value="woman">女</Radio></Radio.Group></Form.Item><Form.Item name="work" label="工作" rules={[{required: true,message: '请选择工作',},]}><Select value={this.state.formData.work} onChange={(e) => this.changeFormItem(e, 'work')} options={this.workList}></Select></Form.Item><Form.Item name="birthDate" label="出生日期" rules={[{required: true,message: '请选择出生日期',},]}><DatePicker showTime onChange={(date, dateString) => this.changeDate(date, dateString)} defaultValue={dayjs(this.state.formData.birthDate, 'YYYY/MM/DD')} format='YYYY/MM/DD' /></Form.Item><Form.Item name="desc" label="描述"><TextAreashowCountmaxLength={100}style={{height: 120,marginBottom: 24,}}value={this.state.formData.desc}onChange={(e) => this.changeFormItem(e, 'desc')}placeholder="请输入描述内容"/></Form.Item></Form></div>)}
})export default forwardRef((props, ref) => {return <GlobalForm {...props} forwardRef={ref}></GlobalForm>
})
公共外套组件 withRouter.jsx
import {useLocation,useNavigate,useParams,} from "react-router-dom";function withRouter(Component) {function ComponentWithRouterProp(props) {let location = useLocation();let navigate = useNavigate();let params = useParams();return (<Component{...props}router={{ location, navigate, params }}/>);}return ComponentWithRouterProp;}export default withRouter
相关文章:
react实现列表增删改查的小demo(class组件版)
前言 react的语法上就是比vue麻烦不少,既然要开手动挡,那就开吧,一个基础的demo 效果图 列表 新增弹窗 编辑弹框 新增一条数据后的效果 代码 根组件 index.jsx import React, { Component,createRef} from react import withRouter from ../../utils/withRouter import G…...
运行批处理文件,Windows 10至少提供了三种方法,有的可以设置定时运行
Windows 10至少有三种写入批处理文件的方法。你可以使用命令提示符或文件资源管理器按需运行它们。你可以使用任务计划程序配置脚本,以便按计划运行。或者,你可以将批处理文件保存在“启动”文件夹中,让系统在你登录帐户后立即运行它们。 如果要按需运行脚本,可以使用文件…...
C++ detach线程的归属权和控制权交给runtime library的原因
在C中,std::thread的detach操作将线程的归属权和控制权都转移给了C运行时库(runtime library)。这是因为detach操作的目的是告诉C运行时库,你不再关心这个线程的状态,它可以在后台独立运行,而不需要等待主线…...
Android应用集成RabbitMQ消息处理指南
Android应用集成RabbitMQ消息处理指南 RabbitMQ1、前言2、RabbitMQ简介2.1、什么是RabbitMQ2.2、RabbitMQ的特点2.3、RabbitMQ的工作原理2.4、RabbitMQ中几个重要的概念 3、在Android Studio中集成RabbitMQ3.1、在Manifest中添加权限:3.2、在build.gradle(:app)下添…...
爆改86㎡户型,中式禅意,自然诗意!福州中宅装饰,福州装修
自然诗意 中式禅意 东方风韵,涟漪泛晕。 ——致生活感的“空间”,最美的家 案例简介 作品:泛晕 风格:新中式 面积:86平方 楼盘:长乐中南樾府 中国风与现代风混搭 木元素是中国风表达中最具灵魂般的存…...
LVGL库入门 02 - 布局
1、简单布局 可以使用 lv_obj_set_pos(obj, x, y) 调整一个控件的位置(或者使用类似的函数单独调整一个方向的坐标),将它放在相对父容器左上角的合适位置。不过这种布局方式非常死板,因为绝对坐标一旦设定就不能自动调整…...
利用Vue2实现印章徽章组件
需要实现的组件效果: 该组件有设置颜色、大小、旋转度数和文本内容功能。 一、组件实现代码 <template><divclass"first-ring"v-bind"getBindValue":class"getStampBadgeClass":style"{ transform: rotate(${rotate}…...
金麟国际用工-全新蓝领跨境就业服务平台
金麟国际用工-全新蓝领跨境就业服务平台 金麟国际用工平台是一个引领时代的蓝领跨境就业服务平台,专为蓝领求职者和雇主提供一个全面、便捷、高效的就业对接环境。这个平台通过其强大的数字化系统,包括客户管理系统、岗位信息系统和智能营销工具等&…...
性能测试知多少---并发用户
在做性能测试的时候,我们常常听到并发用户、响应时间、吞吐量专业术语,也许大家都理解,这里有一个理解的层次与深度概念。最近有看断念《软件性能详解与案例分析》一书,看了他的讲解,原来我对这些术语的理解还是比较肤…...
自动驾驶算法(三):RRT算法讲解与代码实现(基于采样的路径规划)
目录 1 RRT算法原理 2 RRT算法代码解析 3 RRT完整代码 1 RRT算法原理 RRT算法的全称是快速扩展随机树算法(Rapidly Exploring Random Tree),它的想法就是从根结点长出一棵树当树枝长到终点的时候这样就能找到从终点到根节点的唯一路径。 算法流程: 首先…...
基于SSM的酒店客房预定管理系统
基于SSM的酒店客房预定管理系统的设计与实现~ 开发语言:Java数据库:MySQL技术:SpringSpringMVCMyBatis工具:IDEA/Ecilpse、Navicat、Maven 系统展示 前台主页 客房详情 登录界面 管理员界面 用户界面 摘要 基于SSM(…...
IDEA初步入门
1 安装 现在的系统更迭很快,很多软件都只支持win10 和 11了,但我们过时党还在用win7. 所以就必须找到合适的版本。在windows 7 64位系统下,可以使用IDEA 2020.1.4版本。 在Jetbrain官方下,找到历史版本,找到windows版…...
《Webpack 5 基础配置》- 禁止在出现编译错误或警告时,覆盖浏览器全屏显示
Webpack5 overlay 配置地址默认编译错误或警告为 true,即浏览器全屏显示;overlay 属性可以是 boolean 型,也可是 object 类型;还有其它设置说明,详见上述官网地址; module.exports {devServer: {client: {…...
echart 饼图怎么让图形铺满整个div
1.原效果(未铺满):原配置 2.如果想要铺满,需要设置radius ,radius的意思是 第一个元素为内环半径,第二个参数为外环半径; 如果想要填满的话直接写[0,100%],不过第一个为0后就不是圆环里&#…...
回归预测 | Matlab实现WOA-CNN-SVM鲸鱼算法优化卷积神经网络-支持向量机的多输入单输出回归预测
回归预测 | Matlab实现WOA-CNN-SVM鲸鱼算法优化卷积神经网络-支持向量机的多输入单输出回归预测 目录 回归预测 | Matlab实现WOA-CNN-SVM鲸鱼算法优化卷积神经网络-支持向量机的多输入单输出回归预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.WOA-CNN-SVM鲸鱼算法…...
arm-none-eabi-gcc下实现printf的两种方式
方式1,移植第三方printf库: 1. 下载地址:https://github.com/mpaland/printf 2. 拷贝其中的printf.c和printf.h到本地; 3. 重新实现 void _putchar(char character) 接口,使用具体串口发送ch数据,如在 u…...
组件库开发
组件库开发 环境搭建 menorepo pnpmpnpm-workspacelerna 7.4.2 (已全局安装lerna) 1、初始化 1.1 新建项目目录root 1.2 在目录root中使用pnpm初始化packages.json文件,新建 pnpm-workspace.yaml文件, packages/文件夹 pnp…...
【python基础】魔法参数*args, **kwargs的使用
文章目录 前言一、*args 和 **kwargs 是什么?二、*args 的用法打包参数:将不定数量的参数传递给一个函数拆分参数:调用一个函数 三、**kwargs 的用法打包参数:将不定数量的参数传递给一个函数拆分参数:调用一个函数 四…...
Android Icon 添加水印 Python脚本
源代码 # -*- coding: utf-8 -*- from PIL import Image 图片合成def mergePictureLXJ():commonIcon Image.open("icon.png")markIcon Image.open("领现金.png")markLayer Image.new(RGBA, commonIcon.size, (0, 0, 0, 0))markLayer.paste(markIcon, (0…...
选择Centos系统需不需要带SElinux?
CentOS 7的SELinux代表"Security-Enhanced Linux",它是一个Linux操作系统的安全增强功能。SELinux是一个强制访问控制(Mandatory Access Control,MAC)系统,它在操作系统级别提供了更加精细的访问控制和安全策…...
【网络】每天掌握一个Linux命令 - iftop
在Linux系统中,iftop是网络管理的得力助手,能实时监控网络流量、连接情况等,帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...
Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动
一、前言说明 在2011版本的gb28181协议中,拉取视频流只要求udp方式,从2016开始要求新增支持tcp被动和tcp主动两种方式,udp理论上会丢包的,所以实际使用过程可能会出现画面花屏的情况,而tcp肯定不丢包,起码…...
【力扣数据库知识手册笔记】索引
索引 索引的优缺点 优点1. 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度(创建索引的主要原因)。3. 可以加速表和表之间的连接,实现数据的参考完整性。4. 可以在查询过程中,…...
【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例
文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...
oracle与MySQL数据库之间数据同步的技术要点
Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异,它们的数据同步要求既要保持数据的准确性和一致性,又要处理好性能问题。以下是一些主要的技术要点: 数据结构差异 数据类型差异ÿ…...
HashMap中的put方法执行流程(流程图)
1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中,其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下: 初始判断与哈希计算: 首先,putVal 方法会检查当前的 table(也就…...
基于 TAPD 进行项目管理
起因 自己写了个小工具,仓库用的Github。之前在用markdown进行需求管理,现在随着功能的增加,感觉有点难以管理了,所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD,需要提供一个企业名新建一个项目&#…...
华为OD机考-机房布局
import java.util.*;public class DemoTest5 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseSystem.out.println(solve(in.nextLine()));}}priv…...
wpf在image控件上快速显示内存图像
wpf在image控件上快速显示内存图像https://www.cnblogs.com/haodafeng/p/10431387.html 如果你在寻找能够快速在image控件刷新大图像(比如分辨率3000*3000的图像)的办法,尤其是想把内存中的裸数据(只有图像的数据,不包…...
nnUNet V2修改网络——暴力替换网络为UNet++
更换前,要用nnUNet V2跑通所用数据集,证明nnUNet V2、数据集、运行环境等没有问题 阅读nnU-Net V2 的 U-Net结构,初步了解要修改的网络,知己知彼,修改起来才能游刃有余。 U-Net存在两个局限,一是网络的最佳深度因应用场景而异,这取决于任务的难度和可用于训练的标注数…...
