前言:如下內容基於React全家桶+AntD實戰課程的學習實踐過程記錄。最終成果github地址:https://github.com/66Web/react-antd-manager,歡迎star。javascript
1、項目工程化概念 java
2、BaseForm的封裝react
城市管理中FilterForm子組件:ios
訂單管理中FilterForm子組件:git
員工管理中FilterForm子組件:github
【項目工程化】:表單封裝ajax
const formList = this.props.formList;
const {getFieldDecorator } = this.props.form; <FormItem label={label} key={field}> { getFieldDecorator([field])( <Input type="text" style={{width: width}} placeholder={placeholder}/> ) } </FormItem>
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數據 axios
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組件代碼:antd
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)
3、列表數據請求封裝less
每一個管理模塊幾乎都有一個requestList()調用axios.ajax請求Easy Mock接口中的數據。
依據【項目工程化】思想,封裝這部分代碼,簡化開發過程。
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) }
4、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 }) }
【項目工程化】:封裝可複用代碼,擴展複選列表項功能
/** * 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>
注:項目來自慕課網