【共享单车】—— React后台管理系统开发手记:项目工程化开发
作者:互联网
前言:以下内容基于React全家桶+AntD实战课程的学习实践过程记录。最终成果github地址:https://github.com/66Web/react-antd-manager,欢迎star。
一、项目工程化概念
二、BaseForm的封装
城市管理中FilterForm子组件:
订单管理中FilterForm子组件:
员工管理中FilterForm子组件:
【项目工程化】:表单封装
- components->BaseForm->index.js
- 关键:抽象出formList,根据formList中的item.type判断要渲染的AnTD表单类型
const formList = this.props.formList;
- 实现表单数据的双向绑定:getFieldDecorator
const {getFieldDecorator } = this.props.form; <FormItem label={label} key={field}> { getFieldDecorator([field])( <Input type="text" style={{width: width}} placeholder={placeholder}/> ) } </FormItem>
- 获取组件中全部表单控件的内容:getFieldsValue()
handleFilterSubmit = () => { let fieldsValue = this.props.form.getFieldsValue(); this.props.filterSubmit(fieldsValue); } //order->index.js中 <BaseForm formList={this.formList} filterSubmit={this.handleFilter}/> handleFilter = (params) => { this.params = params; this.requestList(); }
-
order->index.js中:按照AntD 的getFieldDecorator.option规则定义formList数据
formList = [ { type: 'SELECT', label: '城市', field: 'city_id', placeholder: '全部', initialValue: '1', width: 80, list: [ {id: '0', name: '全部'}, {id: '1', name: '北京'}, {id: '2', name: '天津'}, {id: '3', name: '上海'} ] }, { type: '时间查询' }, { type: 'SELECT', label: '订单状态', field: 'order_status', placeholder: '全部', initialValue: '1', width: 80, list: [ {id: '0', name: '全部'}, {id: '1', name: '进行中'}, {id: '2', name: '结束行程'} ] } ]
-
BaseForm组件代码:
import React from 'react' import { Input, Select, Form, Button, Checkbox, DatePicker} from 'antd' import Utils from '../../utils/utils' const FormItem = Form.Item; class FilterForm extends React.Component{ handleFilterSubmit = () => { let fieldsValue = this.props.form.getFieldsValue(); this.props.filterSubmit(fieldsValue); } reset = () => { this.props.form.resetFields(); } initFormList = () => { const {getFieldDecorator } = this.props.form; const formList = this.props.formList; const formItemList = []; if(formList && formList.length>0){ formList.forEach((item, i) => { let label = item.label; let field = item.field; let initialValue = item.initialValue || ''; let placeholder = item.placeholder; let width = item.width; if(item.type == '时间查询'){ const begin_time = <FormItem label="订单时间" key={field}> { getFieldDecorator('begin_time')( <DatePicker showTime={true} placeholder={placeholder} format="YYYY-MM-DD HH:mm:ss"/> ) } </FormItem>; formItemList.push(begin_time); //~后省略冒号:label="~" colon={false} const end_time = <FormItem key={field}> { getFieldDecorator('end_time')( <DatePicker showTime={true} placeholder={placeholder} format="YYYY-MM-DD HH:mm:ss"/> ) } </FormItem>; formItemList.push(end_time); }else if(item.type == 'INPUT'){ const INPUT = <FormItem label={label} key={field}> { getFieldDecorator([field])( <Input type="text" style={{width: width}} placeholder={placeholder}/> ) } </FormItem>; formItemList.push(INPUT); }else if(item.type == 'SELECT'){ const SELECT = <FormItem label={label} key={field}> { getFieldDecorator([field],{ initialValue: initialValue })( <Select style={{width: width}} placeholder={[placeholder]} > {Utils.getOptionList(item.list)} </Select> ) } </FormItem>; formItemList.push(SELECT); }else if(item.type == 'CHECKBOX'){ const CHECKBOX = <FormItem label={label} key={field}> { getFieldDecorator([field],{ valuePropName: 'checked', initialValue: initialValue //true | false })( <Checkbox> {label} </Checkbox> ) } </FormItem>; formItemList.push(CHECKBOX); }else if(item.type == 'DATE'){ const DATEPICKER = <FormItem label={label} key={field}> { getFieldDecorator([field])( <DatePicker showTime={true} placeholder={placeholder} format="YYYY-MM-DD HH:mm:ss"/> ) } </FormItem>; formItemList.push(DATEPICKER); } }) } return formItemList; } render(){ return ( <Form layout="inline"> {this.initFormList()} <FormItem> <Button type="primary" style={{margin:'0 10px'}} onClick={this.handleFilterSubmit}>查询</Button> <Button onClick={this.reset}>重置</Button> </FormItem> </Form> ) } } export default Form.create({})(FilterForm)
三、列表数据请求封装
每个管理模块几乎都有一个requestList()调用axios.ajax请求Easy Mock接口中的数据。
依据【项目工程化】思想,封装这部分代码,简化开发过程。
- src->axios->index.js中:定义requestList方法,接收_this、url、params、isMock参数
static requestList(_this, url, params, isMock){ var data = { params: params, isMock //使用Mock数据 } this.ajax({ url, data }).then((data) => { if(data && data.list){ let list = data.list.item_list.map((item, index) => { item.key = index; return item; }); _this.setState({ list, selectedRowKeys: [],//重置 pagination:Utils.pagination(data,(current)=>{ _this.params.page = current; _this.requestList(); }) }) } }) }
-
order->index.js中:requestList()中直接调用axios.requestList()即可获取接口数据
requestList = () => { axios.requestList(this, '/order/list', this.params, true) }
四、ETable表格封装
原城市管理、订单管理:数据列表实现都需要以下内容
<div className="content-wrap"> <Table bordered columns={columns} dataSource={this.state.list} pagination={this.state.pagination} rowSelection= {rowSelection} onRow={(record, index) => { return { onClick: () => { this.onRowClick(record, index); } } }} /> </div>
单选列表项:定义selectedRowKeys和rowSelection、监听onRow事件
const selectedRowKeys = this.state.selectedRowKeys; const rowSelection = { type: 'radio', selectedRowKeys }
onRowClick = (record, index) => { let selectKey = [index]; this.setState({ selectedRowKeys: selectKey, selectedItem: record }) }
【项目工程化】:封装可复用代码,扩展复选列表项功能
- utils->uitils.js:添加ETable行点击通用函数,判断选择框变更传入的参数是否有selectedIds,设置不同的state内容
/** * ETable 行点击通用函数 * @param {*选中行的索引} selectedRowKeys * @param {*选中行对象} selectedItem */ updateSelectedItem(selectedRowKeys, selectedRows, selectedIds) { if (selectedIds) { this.setState({ selectedRowKeys, selectedIds: selectedIds, selectedItem: selectedRows }) } else { this.setState({ selectedRowKeys, selectedItem: selectedRows }) } }
-
components->ETable->index.js:传入的this.props中若有selectedIds,设置checkbox渲染数据,否则,设置radio
import React from 'react' import Utils from '../../utils/utils' import {Table} from 'antd' import "./index.less" export default class ETable extends React.Component { state = {} //处理行点击事件 onRowClick = (record, index) => { let rowSelection = this.props.rowSelection; if(rowSelection == 'checkbox'){ let selectedRowKeys = this.props.selectedRowKeys; let selectedIds = this.props.selectedIds; let selectedItem = this.props.selectedItem || []; if (selectedIds) { const i = selectedIds.indexOf(record.id); if (i == -1) {//避免重复添加 selectedIds.push(record.id) selectedRowKeys.push(index); selectedItem.push(record); }else{ selectedIds.splice(i,1); selectedRowKeys.splice(i,1); selectedItem.splice(i,1); } } else { selectedIds = [record.id]; selectedRowKeys = [index] selectedItem = [record]; } this.props.updateSelectedItem(selectedRowKeys,selectedItem || {},selectedIds); }else{ let selectKey = [index]; const selectedRowKeys = this.props.selectedRowKeys; if (selectedRowKeys && selectedRowKeys[0] == index){ return; } this.props.updateSelectedItem(selectKey,record || {}); } }; // 选择框变更 onSelectChange = (selectedRowKeys, selectedRows) => { let rowSelection = this.props.rowSelection; const selectedIds = []; if(rowSelection == 'checkbox'){ selectedRows.map((item)=>{ selectedIds.push(item.id); }); this.setState({ selectedRowKeys, selectedIds:selectedIds, selectedItem: selectedRows[0] }); } this.props.updateSelectedItem(selectedRowKeys,selectedRows[0],selectedIds); }; onSelectAll = (selected, selectedRows, changeRows) => { let selectedIds = []; let selectKey = []; selectedRows.forEach((item,i)=> { selectedIds.push(item.id); selectKey.push(i); }); this.props.updateSelectedItem(selectKey,selectedRows[0] || {},selectedIds); } getOptions = () => { let p = this.props; const name_list = { "订单编号":170, "车辆编号":80, "手机号码":96, "用户姓名":70, "密码":70, "运维区域":300, "车型":42, "故障编号":76, "代理商编码":97, "角色ID":64 }; if (p.columns && p.columns.length > 0) { p.columns.forEach((item)=> { //开始/结束 时间 if(!item.title){ return } if(!item.width){ if(item.title.indexOf("时间") > -1 && item.title.indexOf("持续时间") < 0){ item.width = 132 }else if(item.title.indexOf("图片") > -1){ item.width = 86 }else if(item.title.indexOf("权限") > -1 || item.title.indexOf("负责城市") > -1){ item.width = '40%'; item.className = "text-left"; }else{ if(name_list[item.title]){ item.width = name_list[item.title]; } } } item.bordered = true; }); } const { selectedRowKeys } = this.props; const rowSelection = { type: 'radio', selectedRowKeys, onChange: this.onSelectChange, onSelect:(record, selected, selectedRows)=>{ console.log('...') }, onSelectAll:this.onSelectAll }; let row_selection = this.props.rowSelection; // 当属性未false或者null时,说明没有单选或者复选列 if(row_selection===false || row_selection === null){ row_selection = false; }else if(row_selection == 'checkbox'){ //设置类型未复选框 rowSelection.type = 'checkbox'; }else{ //默认未单选 row_selection = 'radio'; } return <Table className="card-wrap page-table" bordered {...this.props} rowSelection={row_selection?rowSelection:null} onRow={(record,index) => ({ onClick: ()=>{ if(!row_selection){ return; } this.onRowClick(record,index) } })} /> }; render = () => { return ( <div> {this.getOptions()} </div> ) } }
-
order->index.js中:应用Eable组件实现
import ETable from './../../components/ETable' <div className="content-wrap"> <ETable columns={columns} updateSelectedItem={Utils.updateSelectedItem.bind(this)} selectedRowKeys={this.state.selectedRowKeys} //selectedIds={this.state.selectedIds} selectedItem={this.state.selectedItem} dataSource={this.state.list} pagination={this.state.pagination} /> </div>
注:项目来自慕课网
标签:item,selectedRowKeys,props,selectedIds,const,index,let 来源: https://www.cnblogs.com/ljq66/p/10222985.html