本实文主要是用react+elementUI实现一个后台管理系统中最常见的功能,表格(增删改查、分页); 新增和修改弹窗是一个公共的子组件。接口是用node(express)实现,接口文章链接https://blog.csdn.net/CuiCui_web/article/details/107109689
先引入要使用的组件及方法
import React, { Component } from "react"; import axios from 'axios'; // 引入axios import { Table,Button, MessageBox, Message, Pagination, Form, Input, Layout} from 'element-react'; import './table.scss' // 引入样式文件编写table部分的代码以及数据定义
export default class table extends Component { constructor(props) { super(props); this.state = { // 表格的列 columns_student_info: [ { label: "姓名", prop: "name",align:'center' }, { label: "年龄", prop: "age",align:'center' }, { label: "地址", prop: "address",align:'center' }, { label: "操作", width:100, render: (row, column, index)=>{ return <span> {/*<Button type="text" size="small" onClick={ this. }>查看</Button>*/} <Button type="text" size="small" onClick={ this.updateClick.bind(this,row,index) }>编辑</Button> <Button type="text" size="small" onClick={ this.deleteClick.bind(this,row,index) }>删除</Button> </span> } } ], students_list:[], // 表格数据 // 分页数据定义 page: { pageSize: 5, pageCurrent: 1, total: 0, }, form:{ // 查询条件 name: '' } } } } /** 改变页大小方法 */ onSizeChange=(size)=>{ const page = Object.assign(this.state.page, { pageSize: size }) this.setState({ page: page }) } /** 改变当前是第几页 */ onCurrentChange=(current)=>{ const page = Object.assign( this.state.page, { pageCurrent: current }) this.setState({ page: page }) } // 查询条件数据实时更新 onChange(key, value) { this.setState({ form: Object.assign(this.state.form, { [key]: value }) }); } render() { return ( <div className="table-demo"> <h2 >调用node编写接口数据</h2> <div className="flex"> <div className="flex" style={{ width: "80%" }}> <Form > <Layout.Row gutter="20"> <Layout.Col span="16"> <Form.Item label="学生姓名" labelWidth="80"> <Input value={this.state.form.name} onChange={this.onChange.bind(this, 'name')}></Input> </Form.Item> </Layout.Col> <Layout.Col span="8"> <Button style={{ height:"35px" }} type="primary" onClick={this.getData}>查询</Button> </Layout.Col> </Layout.Row> </Form> </div> <Button style={{ height:"35px" }} type="primary" onClick={this.clicked}>新增</Button> </div> <Table style={{ width:'100%' }} height={200} border columns={ this.state.columns_student_info } data={ this.state.list } /> <Pagination layout="total, sizes, prev, pager, next, jumper" total={this.state.page.total} pageSizes={[5,10,20]} pageSize={ this.state.page.pageSize} currentPage={this.state.page.pageCurrent} onSizeChange={this.onSizeChange} onCurrentChange={this.onCurrentChange} /> </div> ) }上述就是一个没有请求接口的表格数据,可以使用假数据查看效果。
注: 1、 弹窗中visible是通过this.props.dialogVisible拿去父组件中设置的值,从而在父组件中控制这个值是true还是fasle; 标题也是同理,在父中进行改变,子直接使用即可this.props.title 2、类似vue中的$emit,react怎么将自己的事件以及数据给父,在父中执行呢?
this.props.toSubmit(this.state.form) 在父中,使用子组件的标签上直接绑定toSubmit方法即可3、编辑弹窗与新增弹窗的区别就是判断id是否存在,在vue中,我们可以用watch监听;那么react中如何使用呢?
//监听组件传递的值: componentWillReceiveProps(newProps) { if(newProps.formObj.id){ this.setState({ form: newProps.formObj }) } }这个方法是判断,当id存在,就将组件传递来的值赋值给表单对象。 4、 弹窗x按钮方法直接调用取消方法onCancel={ this.handleReset }
1、引入子组件
import AddInfo from './addInfo'2、数据定义
constructor(props) { super(props); this.state = { dialogVisible: false ,// 弹窗是否打开 title: '新增弹窗', // 新增弹窗, formObj: {}, } }3、组件使用
render() { return ( <div className="table-demo"> <AddInfo title={ this.state.title } formObj={ this.state.formObj } dialogVisible={this.state.dialogVisible} toSubmit={ this.submitClick } toReset={ this.resetClick }/> </div> ) }4、方法定义:
/** 查询接口 */ getData = () => { axios({ url: 'http://localhost:3000/demo', method: 'post', data:{ pageSize: this.state.page.pageSize, pageCurrent: this.state.page. pageCurrent, name: this.state.form.name } }) .then((response) => { console.log(response,'gggggggggggg') const page = Object.assign( this.state.page, { total: response.data.total }) this.setState({ list: response.data.list, page: page }) }) .catch(function (error) { console.log(error); }); } /** 会在组件已经渲染到Dom中后运行 */ componentDidMount(){ this.getData() } /** 组件卸载方法 */ componentWillUnmount(){ } /** 新增按钮事件 */ clicked = ()=> { this.setState({ dialogVisible: true,title: '新增信息' }) } /** 编辑按钮事件 */ updateClick=(row)=>{ console.log(row) if(row.id){ this.setState({ title: '修改信息', dialogVisible: true }) } this.setState({ formObj: Object.assign({},row) }) } /** 弹窗确定按钮事件 */ submitClick=(val)=>{ console.log(val,'ggg') // axios.post('http://localhost:3000/demo_add') axios({ url: val.id? 'http://localhost:3000/demo_update': 'http://localhost:3000/demo_add', method: 'post', data:{ val } }) .then((response) => { console.log(response) Message({ type: 'success', message: response.data }); this.setState({ dialogVisible: false }) this.getData() }) .catch(function (error) { console.log(error); }); } /** 弹窗取消按钮事件 */ resetClick=()=>{ this.setState({ dialogVisible: false }) } /** 删除按钮方法 */ deleteClick=(row,index)=>{ MessageBox.confirm('此操作将永久删除该文件, 是否继续?', '提示', { type: 'warning' }).then(() => { axios({ url:'http://localhost:3000/demo_del', method: 'delete', data:{ id: row.id } }) .then((response) => { Message({ type: 'success', message: '删除成功!' }); this.getData() }) .catch(function (error) { console.log(error); }); }).catch(() => { Message({ type: 'info', message: '已取消删除' }); }); } /** 改变页大小方法 */ onSizeChange=(size)=>{ const page = Object.assign(this.state.page, { pageSize: size }) this.setState({ page: page }) this.getData() } /** 改变当前是第几页 */ onCurrentChange=(current)=>{ const page = Object.assign( this.state.page, { pageCurrent: current }) this.setState({ page: page }) this.getData() }注意: 1、 如何修改对象中一个属性值,利用es6语法
const page = Object.assign(this.state.page, { pageSize: size }) this.setState({ page: page })2、 类型vue中的生命周期方法,进入,即调接口渲染数据
/** 会在组件已经渲染到Dom中后运行 */ componentDidMount(){ this.getData() }最后贴上完整的父组件的代码:
import React, { Component } from "react"; import axios from 'axios'; // 引入axios import { Table,Button,Dialog,MessageBox, Message, Pagination, Form, Input, Layout} from 'element-react'; import './table.scss' // 引入样式文件 import AddInfo from './addInfo' export default class table extends Component { constructor(props) { super(props); this.state = { // 表格表头 columns_student_info: [ { label: "姓名", prop: "name",align:'center' }, { label: "年龄", prop: "age",align:'center' }, { label: "地址", prop: "address",align:'center' }, { label: "操作", width:100, render: (row, column, index)=>{ return <span> <Button type="text" size="small" onClick={ this.updateClick.bind(this,row,index) }>编辑</Button> <Button type="text" size="small" onClick={ this.deleteClick.bind(this,row,index) }>删除</Button> </span> } } ], students_list:[], // 表格数据 dialogVisible: false ,// 弹窗是否打开 title: '新增弹窗', // 新增弹窗, formObj: {}, // 子组件表单数据 page: { // 分页 pageSize: 5, pageCurrent: 1, total: 0, }, form:{ // 查询条件 name: '' } } } /** 查询接口 */ getData = () => { axios({ url: 'http://localhost:3000/demo', method: 'post', data:{ pageSize: this.state.page.pageSize, pageCurrent: this.state.page. pageCurrent, name: this.state.form.name } }) .then((response) => { const page = Object.assign( this.state.page, { total: response.data.total }) this.setState({ list: response.data.list, page: page }) }) .catch(function (error) { console.log(error); }); } /** 会在组件已经渲染到Dom中后运行 */ componentDidMount(){ this.getData() } /** 组件卸载方法 */ componentWillUnmount(){ } /** 新增按钮事件 */ clicked = ()=> { this.setState({ dialogVisible: true,title: '新增信息' }) } /** 编辑按钮事件 */ updateClick=(row)=>{ console.log(row) if(row.id){ this.setState({ title: '修改信息', dialogVisible: true }) } this.setState({ formObj: Object.assign({},row) }) } /** 弹窗确定按钮事件 */ submitClick=(val)=>{ console.log(val,'ggg') // axios.post('http://localhost:3000/demo_add') axios({ url: val.id? 'http://localhost:3000/demo_update': 'http://localhost:3000/demo_add', method: 'post', data:{ val } }) .then((response) => { console.log(response) Message({ type: 'success', message: response.data }); this.setState({ dialogVisible: false }) this.getData() }) .catch(function (error) { console.log(error); }); } /** 弹窗取消按钮事件 */ resetClick=()=>{ this.setState({ dialogVisible: false }) } /** 删除按钮方法 */ deleteClick=(row,index)=>{ MessageBox.confirm('此操作将永久删除该文件, 是否继续?', '提示', { type: 'warning' }).then(() => { axios({ url:'http://localhost:3000/demo_del', method: 'delete', data:{ id: row.id } }) .then((response) => { Message({ type: 'success', message: '删除成功!' }); this.getData() }) .catch(function (error) { console.log(error); }); }).catch(() => { Message({ type: 'info', message: '已取消删除' }); }); } /** 改变页大小方法 */ onSizeChange=(size)=>{ const page = Object.assign(this.state.page, { pageSize: size }) this.setState({ page: page }) this.getData() } /** 改变当前是第几页 */ onCurrentChange=(current)=>{ const page = Object.assign( this.state.page, { pageCurrent: current }) this.setState({ page: page }) this.getData() } onChange(key, value) { this.setState({ form: Object.assign(this.state.form, { [key]: value }) }); } render() { return ( <div className="table-demo"> <h2 >调用node编写接口数据</h2> <div className="flex"> <div className="flex" style={{ width: "80%" }}> <Form > <Layout.Row gutter="20"> <Layout.Col span="16"> <Form.Item label="学生姓名" labelWidth="80"> <Input value={this.state.form.name} onChange={this.onChange.bind(this, 'name')}></Input> </Form.Item> </Layout.Col> <Layout.Col span="8"> <Button style={{ height:"35px" }} type="primary" onClick={this.getData}>查询</Button> </Layout.Col> </Layout.Row> </Form> </div> <Button style={{ height:"35px" }} type="primary" onClick={this.clicked}>新增</Button> </div> <Table style={{ width:'100%' }} height={200} border columns={ this.state.columns_student_info } data={ this.state.list } /> <Pagination layout="total, sizes, prev, pager, next, jumper" total={this.state.page.total} pageSizes={[5,10,20]} pageSize={ this.state.page.pageSize} currentPage={this.state.page.pageCurrent} onSizeChange={this.onSizeChange} onCurrentChange={this.onCurrentChange} /> <AddInfo title={ this.state.title } formObj={ this.state.formObj } dialogVisible={this.state.dialogVisible} toSubmit={ this.submitClick } toReset={ this.resetClick }/> </div> ) } }样式文件代码:
.table-demo{ h2{ margin-bottom:10px; &:not(:first-child){ margin-top:20px; } } .flex-end{ display: flex; justify-items: end; justify-content: flex-end; padding:0px 0 10px; } /deep/.el-dialog__header{ padding:0 0 10px !important; margin-bottom:20px; border-bottom:1px solid #ddd; } .dialog-footer{ display: flex; justify-content: flex-end; } .flex{ display: flex; justify-content: space-between; } }