編寫antd配置表單組件
總體思路
- 抽取formitem的配置數組:包含組件類型、名稱、label名稱,相關的opts和擴展的opts,傳遞進入組件
- 組件經過Form.create()進行表單建立,可以帶有form屬性。而且上層組件引用後可以ref的方式獲取form進行操做處理
- 基於form可以抽取出來,上層組件可以對下層組件進行調用和操做,在此基礎上還可以進行擴展配置和擴展功能的實現
- 組件經過props中獲取配置數組,動態生成FormItem的表單元素,實現動態配置表單的功能
- 組件經過在create中的mapPropsToFields中將外部對象數據data綁定到內部表單Item中了
實例實現代碼,基於react和antd,相似的組件實現思路一致
組件js
import React, { PureComponent } from 'react';
import { Row, Form, Input, Col } from 'antd';
import FormItem from 'antd/lib/form/FormItem';
import BaseDataForm from '.';
// 通用組件
class _BaseDataForm extends PureComponent {
// 默認屬性
defaultProps = {
fields: [], // 外部傳遞進來的配置數據
}
state = {
}
getFromItems = () => {
const { form } = this.props;
const { getFieldDecorator } = form;
const { fields, labelCol, wrapperCol } = this.props;
const children = [];// 定義返回值數組
const fieldsinput = fields || [];
const labelColinput = labelCol || 7;
const wrapperColinput = wrapperCol || 15;
const formItemLayout = {
labelCol: { span: labelColinput },
wrapperCol: { span: wrapperColinput },
};
for (let index = 0; index < fieldsinput.length; index += 1) {
const field = fieldsinput[index];
let item = '';
if (field.type === 'Input' || field.type === 'password') {
// this.props.form.getFieldDecorator(id, options) 使用功能這個包裝空間,id等於屬性名
item = getFieldDecorator(field.name, field.fieldDecoratorOps)(
<Input {...field.elementOpts} />
);
}
// 拼裝表格
children.push(
<Col key={index}>
<FormItem {...formItemLayout} label={field.label}>
{item}
</FormItem>
</Col>
);
}
return children;
}
render() {
return (
<Form>
<Row>{this.getFields()}</Row>
</Form>
);
}
}
導入js
// 通過Form.create包裝過的組件會自帶this.props.form
const BaseDataForm = Form.create({
mapPropsToFields: (props) => {
// 把父組件的屬性映射到表單項上(如:把 Redux store 中的值讀出),須要對返回值中的表單域數據用 Form.createFormField 標記,注意表單項將變成受控組件, error 等也須要一併手動傳入
const { fields = [], data = [] } = props;
const values = {};
fields.map(item => {
const fieldName = item.name;
let value = data[fieldName];
if (fieldName.indexOf('.' !== -1)) {
try {
// eslint-disable-next-line no-eval
value = eval('data.' + fieldName);
// 特殊多層結構數據獲取值
} catch (error) {
// eslint-disable-next-line no-console
console.error(error);
}
}
if (value !== undefined && value !== null) {
// 特殊數據處理
}
values[fieldName] = Form.createFormField({ value });
return item;
});
return values;
},
})(_BaseDataForm);
export default BaseDataForm;
實例js
class Test extends PureComponent {
exampleFields = [
{
type: 'Input',
name: 'test',
label: '輸入1',
fieldDecoratorOps: {}, // 表單綁定屬性
elementOpts: {}, // 標籤屬性
},
{
type: 'Input',
name: 'test2',
label: '輸入2',
fieldDecoratorOps: {}, // 表單綁定屬性
elementOpts: {}, // 標籤屬性
},
];
saveFormRef = (form) => {
this.form = from;
}
getFormData = () => {
return this.form.getFieldsValue();
}
render() {
return (
<BaseDataForm
ref={this.saveFormRef} // 經過ref將對應的表單from組件映射出來,可以直接調用
data={{}} // data在建立表單的時候作了一次綁定,這個綁定可以將當前值顯示進去
fields={exampleFields}
/>
);
}
}