当前位置: 首页 > 工具软件 > Zent > 使用案例 >

开发随笔:利用业务组件zent封装表单组件

范朗
2023-12-01

zent封装表单组件

  • zent版本7.4.3
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);

 类似资料: