• Vant React

Form 表单

介绍

用于数据录入、校验,支持输入框、单选框、复选框、文件上传等类型。

引入

import { Form } from "@taroify/core"

代码演示

基础用法

在表单中,每个 Form.Item 代表一个表单项,使用 Field 的 rules 属性定义校验规则。

function BasicForm() {
  const onSubmit = (event: BaseEventOrig<FormProps.onSubmitEventDetail>) => {
    Toast.open(JSON.stringify(event.detail.value))
  }

  return (
    <Form onSubmit={onSubmit}>
      <Toast id="toast" />
      <Cell.Group inset>
        <Form.Item name="username" rules={[{ required: true, message: "请填写用户名" }]}>
          <Form.Label>用户名</Form.Label>
          <Form.Control>
            <Input placeholder="用户名" />
          </Form.Control>
        </Form.Item>
        <Form.Item name="password" rules={[{ required: true, message: "请填写密码" }]}>
          <Form.Label>密码</Form.Label>
          <Form.Control>
            <Input password placeholder="密码" />
          </Form.Control>
        </Form.Item>
        <Field
          name="text"
          label={{ align: "left", children: "文本" }}
          rules={[{ required: true, message: "请填写文本" }]}
        >
          <Input placeholder="请输入文本" />
        </Field>
      </Cell.Group>
      <View style={{ margin: "16px" }}>
        <Button shape="round" block color="primary" formType="submit">
          提交
        </Button>
      </View>
    </Form>
  )
}

校验规则

通过 rules 定义表单校验规则,所有可用字段见下方表格

function FormWithRules() {
  const asyncValidator = (val: any) =>
    new Promise<boolean>((resolve) => {
      Toast.loading("验证中...")

      setTimeout(() => {
        Toast.close("toast")
        resolve(/\d{6}/.test(val))
      }, 1000)
    })

  function onValidate(errors: FormValidError[]) {
    Toast.open({
      style: {
        textAlign: "left",
      },
      message: JSON.stringify(errors, undefined, 2),
    })
  }

  return (
    <Form defaultValues={{ validatorMessage: "abc" }} onValidate={onValidate}>
      <Toast id="toast" />
      <Cell.Group inset>
        <Form.Item name="pattern" rules={[{ pattern: /\d{6}/, message: "请输入正确内容" }]}>
          <Form.Label>文本</Form.Label>
          <Form.Control>
            <Input placeholder="正则校验" />
          </Form.Control>
        </Form.Item>
        <Form.Item
          name="validator"
          rules={[{ validator: (val) => /1\d{10}/.test(val), message: "请输入正确内容" }]}
        >
          <Form.Label>文本</Form.Label>
          <Form.Control>
            <Input placeholder="函数校验" />
          </Form.Control>
        </Form.Item>
        <Form.Item
          name="validatorMessage"
          rules={[{ validator: (val) => `${val ?? ""} 不合法,请重新输入` }]}
        >
          <Form.Label>文本</Form.Label>
          <Form.Control>
            <Input placeholder="校验函数返回错误提示" />
          </Form.Control>
        </Form.Item>
        <Form.Item
          name="asyncValidator"
          rules={[{ validator: asyncValidator, message: "请输入正确内容" }]}
        >
          <Form.Label>文本</Form.Label>
          <Form.Control>
            <Input placeholder="异步函数校验" />
          </Form.Control>
        </Form.Item>
      </Cell.Group>
      <View style={{ margin: "16px" }}>
        <Button shape="round" block color="primary" formType="submit">
          提交
        </Button>
      </View>
    </Form>
  )
}

表单项类型 - 开关

在表单中使用 Switch 组件

<Form.Item name="switch">
  <Form.Label>开关</Form.Label>
  <Form.Control>
    <Switch size={20} />
  </Form.Control>
</Form.Item>

表单项类型 - 复选框

在表单中使用 Checkbox 组件

<Form.Item name="checkbox">
  <Form.Label>复选框</Form.Label>
  <Form.Control>
    <Checkbox shape="square" />
  </Form.Control>
</Form.Item>
<Form.Item name="checkboxGroup">
  <Form.Label>复选框</Form.Label>
  <Form.Control>
    <Checkbox.Group direction="horizontal">
      <Checkbox name="1" shape="square">
        复选框 1
      </Checkbox>
      <Checkbox name="2" shape="square">
        复选框 2
      </Checkbox>
    </Checkbox.Group>
  </Form.Control>
</Form.Item>

表单项类型 - 单选框

在表单中使用 Radio 组件

<Form.Item name="radio">
  <Form.Label>单选框</Form.Label>
  <Form.Control>
    <Radio.Group direction="horizontal">
      <Radio name="1">单选框 1</Radio>
      <Radio name="2">单选框 2</Radio>
    </Radio.Group>
  </Form.Control>
</Form.Item>

表单项类型 - 步进器

在表单中使用 Stepper 组件

<Form.Item name="stepper">
  <Form.Label>步进器</Form.Label>
  <Form.Control>
    <Stepper />
  </Form.Control>
</Form.Item>

表单项类型 - 评分

在表单中使用 Rate 组件

<Form.Item name="rate">
  <Form.Label>评分</Form.Label>
  <Form.Control>
    <Rate />
  </Form.Control>
</Form.Item>

表单项类型 - 滑块

在表单中使用 Slider 组件

<Form.Item name="slider">
  <Form.Label>滑块</Form.Label>
  <Form.Control>
    <Slider />
  </Form.Control>
</Form.Item>

表单项类型 - 文件上传

在表单中使用 Uploader 组件

function UploaderField() {
  const itemRef = useRef<FormItemInstance>()

  function onUpload() {
    chooseImage({
      count: 1,
      sizeType: ["original", "compressed"],
      sourceType: ["album", "camera"],
    }).then(({ tempFiles }) => {
      itemRef.current?.setValue([
        ...(itemRef.current?.getValue() ? [...itemRef.current?.getValue()] : []),
        {
          url: tempFiles[0].path,
          type: tempFiles[0].type,
          name: tempFiles[0].originalFileObj?.name,
        },
      ])
    })
  }

  return (
    <Form.Item ref={itemRef} name="uploader">
      <Form.Label>文件上传</Form.Label>
      <Form.Control>
        <Uploader multiple maxFiles={2} onUpload={onUpload} />
      </Form.Control>
    </Form.Item>
  )
}

表单项类型 - 选择器

在表单中使用 Picker 组件

function PickerField() {
  const itemRef = useRef<FormItemInstance>()
  const [open, setOpen] = useState(false)

  return (
    <>
      <Form.Item ref={itemRef} name="picker" clickable rightIcon={<ArrowRight />}>
        <Form.Label>选择器</Form.Label>
        <Form.Control>
          <Input readonly placeholder="点击选择城市" onClick={() => setOpen(true)} />
        </Form.Control>
      </Form.Item>
      <Popup mountOnEnter={false} open={open} rounded placement="bottom" onClose={setOpen}>
        <Picker
          onCancel={() => setOpen(false)}
          onConfirm={(newValue) => {
            itemRef.current?.setValue(newValue)
            setOpen(false)
          }}
        >
          <Picker.Toolbar>
            <Picker.Button>取消</Picker.Button>
            <Picker.Button>确认</Picker.Button>
          </Picker.Toolbar>
          <Picker.Column>
            <Picker.Option>杭州</Picker.Option>
            <Picker.Option>宁波</Picker.Option>
            <Picker.Option>温州</Picker.Option>
            <Picker.Option>嘉兴</Picker.Option>
            <Picker.Option>湖州</Picker.Option>
          </Picker.Column>
        </Picker>
      </Popup>
    </>
  )
}

表单项类型 - 时间选择器

在表单中使用 DatetimePicker 组件

function DatetimePickerField() {
  const itemRef = useRef<FormItemInstance>()
  const [open, setOpen] = useState(false)

  const formatDate = (date: any) => {
    if (date) {
      const hours = _.padStart(_.toString(date?.getHours()), 2, "0")
      const minutes = _.padStart(_.toString(date?.getMinutes()), 2, "0")
      return `${hours}:${minutes}`
    }
  }

  return (
    <>
      <Form.Item ref={itemRef} name="datetimePicker" clickable rightIcon={<ArrowRight />}>
        <Form.Label>时间选择</Form.Label>
        <Form.Control>
          {(controller) => (
            <Input
              value={formatDate(controller.value)}
              readonly
              placeholder="点击选择时间"
              onClick={() => setOpen(true)}
            />
          )}
        </Form.Control>
      </Form.Item>
      <Popup mountOnEnter={false} open={open} rounded placement="bottom" onClose={setOpen}>
        <DatetimePicker
          type="hour-minute"
          onCancel={() => setOpen(false)}
          onConfirm={(newValue) => {
            itemRef.current?.setValue(newValue)
            setOpen(false)
          }}
        >
          <Picker.Toolbar>
            <Picker.Button>取消</Picker.Button>
            <Picker.Button>确认</Picker.Button>
          </Picker.Toolbar>
        </DatetimePicker>
      </Popup>
    </>
  )
}

表单项类型 - 日历

在表单中使用 Calendar 组件

function CalendarField() {
  const itemRef = useRef<FormItemInstance>()
  const [open, setOpen] = useState(false)

  const formatDate = (date: any) => {
    if (date) {
      const months = _.padStart(_.toString(date?.getMonth() + 1), 2, "0")
      const days = _.padStart(_.toString(date?.getDate()), 2, "0")
      return `${months}-${days}`
    }
  }

  return (
    <>
      <Form.Item ref={itemRef} name="calendar" clickable rightIcon={<ArrowRight />}>
        <Form.Label>日历</Form.Label>
        <Form.Control>
          {(controller) => (
            <Input
              value={formatDate(controller.value)}
              readonly
              placeholder="点击选择日期"
              onClick={() => setOpen(true)}
            />
          )}
        </Form.Control>
      </Form.Item>
      <Popup
        mountOnEnter={false}
        style={{ height: "80%" }}
        open={open}
        rounded
        placement="bottom"
        onClose={setOpen}
      >
        <Popup.Close />
        <Calendar
          type="single"
          onConfirm={(newValue) => {
            itemRef.current?.setValue(newValue)
            setOpen(false)
          }}
        >
          <Calendar.Footer>
            <Calendar.Button type="confirm">确定</Calendar.Button>
          </Calendar.Footer>
        </Calendar>
      </Popup>
    </>
  )
}

API

Form Props

参数 说明 类型 默认值
labelAlign 表单项 label 对齐方式,可选值为 center right string left
controlAlign 表单项 control 对齐方式,可选值为 center right string left
validateTrigger 表单校验触发时机,可选值为 onChangeonSubmit,详见下表 string onBlur
validateFirst 是否在某一项校验不通过时停止校验 boolean false
colon 是否在 label 后面添加冒号 boolean false

Form Events

事件名 说明 回调参数
onSubmit 提交表单且验证通过后触发 event: BaseEventOrig<FormProps.onSubmitEventDetail>
onReset 重置表单后触发 event: BaseEventOrig
onValidate 提交表单且验证不通过后触发 errors: { name: string, errors: string[] }[]
onValuesChange 字段值更新后触发 changedValues: object, allValues: object

Form Methods

通过 ref 可以获取到 Form 实例并调用实例方法。

方法名 说明 参数 返回值
setValues 设置表单值 object -
getValues 获得表单值,支持传入 name 来获得单个或部分表单项 name?: string | string[] object
validate 验证表单,支持传入 name 来验证单个或部分表单项 name?: string | string[] Promise
reset 重置表单 - Promise

validateTrigger 可选值

通过 validateTrigger 属性可以自定义表单校验的触发时机。

描述
onSubmit 仅在提交表单时触发校验
onBlur 在提交表单和输入框失焦时触发校验
onChange 在提交表单和输入框内容变化时触发校验

Form.Item Props

参数 说明 类型 默认值
name 表单项名称,提交表单的标识符 string -
defaultValue 表单项默认值 any -
required 是否显示表单必填星号 boolean false
rules 表单校验规则 FormRule[] -

属性继承自 Cell 组件,更多属性参见:Cell 组件

Rule 数据结构

使用 Form.Item 的 rules 属性可以定义校验规则,可选属性如下:

键名 说明 类型
required 是否为必选字段,当值为空字符串、空数组、undefinednull 时,校验不通过 boolean
message 错误提示文案 string | (value, rule) => string
validator 通过函数进行校验 (value, rule) => boolean | string | Promise
pattern 通过正则表达式进行校验 RegExp
trigger 本项规则的触发时机,可选值为 onChangeonBlur string
formatter 格式化函数,将表单项的值转换后进行校验 (value, rule) => any

Form.Label Props

参数 说明 类型 默认值
align 对齐方式,可选值为 center right string left
colon 是否在 label 后面添加冒号 boolean false

Form.Feedback Props

参数 说明 类型 默认值
align 对齐方式,可选值为 center right string left
status 反馈状态,可选值为 valid warning invalid string -

Form.Control Props

参数 说明 类型 默认值
align 对齐方式,可选值为 center right string left

主题定制

样式变量

组件提供了下列 CSS 变量,可用于自定义样式,使用方法请参考 ConfigProvider 组件。

名称 默认值 描述
form-label-width 6.2em -
form-label-color var(—gray-7) -
form-label-margin-right var(—padding-sm) -
form-label-required-color var(—red) -
form-label-disabled-color var(—gray-5) -
form-item-icon-size 16px * $hd -
form-item-right-icon-color var(—gray-6) -
form-item-right-icon-padding 0 var(—padding-xs) -
form-item-right-icon-margin-right -8px * $hd -
form-item-right-button-margin-left var(—padding-xs) -
form-control-color var(—text-color) -
form-control-min-height var(—cell-line-height) -
form-feedback-font-size var(—font-size-sm) -
form-feedback-valid-color var(—success-color) -
form-feedback-warning-color var(—warning-color) -
form-feedback-invalid-color var(—danger-color) -