zent封装表单组件
1. 利用zent的几个组件
- FormControl: 包裹封装组件,用于为封装的表单组件提供label, invalid等参数,与其他封装的表单组件统一格式
- FieldSet: 包裹封装的外部组件,当FormStrategy.View时,为上级托管的Form组件添加字段name
- Form.useField: 初始化一个model,包括初始值,键值key和值value。这个model中值的改变将会注册到上级的Form中
- FieldUtils中的几个方法:
- useMAppend: 按照顺序从上往下执行回调函数
- usePipe: 按顺序执行函数,且上一个函数的返回值将作为下一个函数的输出
- makeChangeHandler: 指定一个需要改变model的值,注意:源码里这个是一个闭包函数,通过上级传入的value直接改传入model中对应的值
2. 结合官网例子分析
import React, { useCallback, useState } from "react";
import ReactDOM from "react-dom";
import {
Form,
Select,
NumberInput,
FormStrategy,
FormControl,
Button,
FieldSet,
Validators,
FieldUtils
} from "zent";
import "zent/css/index.css";
const { SelectTrigger } = Select;
const countyCodeList = [
{
code: "+86",
zh: "zhongguo",
eng: "china",
value: "中国 +86",
index: 0
},
{
code: "+853",
zh: "aomen",
eng: "Macau",
value: "中国澳门 +853",
index: 1
}
];
const filterHandler = (item, keyword) => {
return (
keyword &&
item.text
.trim()
.toLowerCase()
.indexOf(keyword.trim().toLowerCase()) > -1
);
};
function getValue(e) {
return e.target.value;
}
const ContactPhone = () => {
const select = Form.useField("areacode", 0);
const input = Form.useField("mobile", "", [
Validators.pattern(/^\d{1,10}$/, "请输入正确的手机号")
]);
// 这个counter并没有挂载在任何表单元素上,直接通过fieldUtils进行修改
const counter = Form.useField("counter", 0);
const onSelectChange = FieldUtils.useMAppend(
useCallback(() => (select.isTouched = true), [select]),
FieldUtils.usePipe(getValue, FieldUtils.makeChangeHandler(select))
);
const [countNumber, setCounter] = useState(0);
const handleChange = FieldUtils.useMAppend(
FieldUtils.usePipe(e => {
// 这里直接返回counterNumber + 1作为makeChangeHandler的输入值
setCounter(countNumber + 1);
return countNumber + 1;
// 这里指定修改的对象model为counter,之后counter就会发生改变
}, FieldUtils.makeChangeHandler(counter)),
// 这里直接这样操作的原因是,因为本身NumberInput的回调函数就会传入value,所以直接将value传给makeChangeHandler的回调函数
FieldUtils.makeChangeHandler(input, Form.ValidateOption.Default)
);
return (
<FormControl
className="form-demo-multiple-value"
label="联系方式:"
invalid={!!select.error || !!input.error}
>
<Select
className="areacode"
data={countyCodeList}
filter={filterHandler}
optionValue="index"
optionText="value"
trigger={SelectTrigger}
width={160}
value={select.value}
onChange={onSelectChange}
/>
<NumberInput
className="phone-num"
placeholder="请填写手机号"
width={160}
value={input.value}
{...FieldUtils.useCompositionHandler(input)}
onChange={handleChange}
onBlur={useCallback(() => {
input.isTouched = true;
input.validate();
}, [input])}
/>
<Form.CombineErrors models={[select, input]} />
</FormControl>
);
};
const App = () => {
const form = Form.useForm(FormStrategy.View);
const getFormValues = useCallback(() => {
const values = form.getValue();
console.log(values);
}, [form]);
const resetForm = useCallback(() => {
form.resetValue();
}, [form]);
return (
<Form form={form} layout="horizontal">
<FieldSet name="contactPhone">
<ContactPhone />
</FieldSet>
<div className="zent-form__form-actions">
<Button type="primary" onClick={getFormValues}>
获取表单值
</Button>{" "}
<Button type="primary" outline onClick={resetForm}>
重置表单值
</Button>
</div>
</Form>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);