0.1.7 • Published 5 years ago

@ice/form v0.1.7

Weekly downloads
17
License
MIT
Repository
-
Last release
5 years ago

title: IceForm category: Components

chinese: 表单组件

表单组件

参数(Props)

参数名说明必填类型默认值备注
initialValues表单初始值Nobject{}-
onSubmitsubmit函数Yfunction--
onChange表单变化回调Nfunction-function(values: object, item: object) => void 参数: values: {object} 表单数据 item: {object} 详细 item.name: {string} 变化的组件名 item.value: {string} 变化的数据
rules校验规则Nobject{}-
effects联动规则Narray[]-
layout表单布局Nobject-
renderField自定义 Field 布局Nfunction-function({label, component, error}) => dom 参数: label: {string/element} Field 的 label component: {string/function} 待渲染的控件 error: {string/element} Field 错误提示信息

其他属性比如 styleclassName 等均会传递到 form 标签上。

layout 是个对象,包含 4 个属性:

{
  labelAlign: 'left',       // label 的位置,'left'、'top',默认 'left'
  labelTextAlign: 'right',  // label 文字对齐方式,'left'、'right',默认 'right'
  labelCol: 1,             // label 占的栅格宽度,共 12 等分,默认 2
  wrapperCol: 3,           // 控件占的栅格宽度,共 12 等分,默认 6
}

rules 是一个 Object,key<Field>name 属性值,value 是个数组,数组里面的每一项是一个校验规则,参考 async-validator

<Form
  onSubmit={this.onSubmit}
  style={{color: '#ee7893'}}
  rules={{
    username: [{
      required: true,
      min: 5,
      message: '姓名至少5个字符'
    }],
    age:  [{
      required: true,
      message: '年龄必填'
    }]
  }}
>
  <Field label="姓名:" name="username" component="input" type="text" />
  <Field label="年龄:" name="age" component='input' type="number" />
</Form>

effects 是个数组,写法如下:

<Form
  onSubmit={this.onSubmit}
  effects={[
    {
      field: 'username',
      handler: formCore => {
        if (formCore.getFieldValue('username') === 'ice') {
          formCore.setFieldValue('age', 2)
        }
      }
    }
  ]}
>
  <div>Hello Form</div>
  <Field label="姓名:" name="username" component="input" type="text" />
  <Field label="年龄:" name="age" component='input' type="number" />
  <button type="submit">Submit</button>
</Form>

监听该 fieldonChange 事件,然后设置其他表单项的数据,从而达到联动效果。handler 的参数是 formCore 对象,该对象暴露一些 api 可以设置 value、error、show/hide 等。

Field 组件

参数名说明必填类型默认值备注
label表单项的 labelNstring/element--
name表单项的 nameYstring--
component表单类型,原生 html 标签或者三方组件Nstring/function-'input' 'textarea' Input Radio
value表单项的值N-''-
rules校验规则Nobject or array--
effects联动规则Nobject--
visible显示隐藏当前 FieldNbooleantruetrue/false
setValueFormatter格式化控件渲染值Nfunctionfunction(savedValue) => renderValue
getValueFormatter格式化控件提交值Nfunctionfunction(renderValue) => savedValue
layout设置当前 Field 的布局Nobject同 Form layout当前 Field 的 layout 会覆盖 Form 的 layout
tips提示信息Nstring
valueName控件值的名称,比如,radio 的 valueName 为 'checked',value 为 true/falseNstring比如 Fusion 的 Switch 组件
errorRender自定义 error 渲染Nfunction(error) {}
onChange自定义 onChange 函数Nfunction() {}默认情况下已处理表单的 onChange(eventOrValue) 事件,如果接入的三方控件 onChange 的第一个参数不是 event 或者 value,可以主动设置对应的值。比如,接入控件的 onChange(xxx, value) 第二个参数才是 value,则可以手动设置 formCore.setValue(fieldname, value)

styleclassName 属性会传递到 Field 最外层 dom 上,其他属性会传递到 component 上,如果没有 component 但有 children,则属性传递到 children 上。

Fieldruleseffects 不需要 name 作为 key 了,写法如下:

<Form onSubmit={this.onSubmit}>
  <Field label="姓名:" name="username" component="input" type="text" />
  <Field label="昵称:" name="nickname" component="input" type="text" effects={{
    handler: formCore => {
      if (formCore.getFieldValue('nickname') === 'snow') {
        formCore.setFieldProps('age', {
          visible: true,
        });
      } else {
        formCore.setFieldProps('age', {
          visible: false,
        });
      }
    }
  }} />
  <Field label="年龄:" name="age" component='input' type="number" rules={[{
    required: true,
    message: '年龄必填'
  }]} />
  <button type="submit">Submit</button>
</Form>

FieldArray 组件

FieldArray 表示渲染数组类型的数据,属性同 Field:

<Form
  onSubmit={this.onSubmit}
>
  <FieldArray label="新增顾客:" name="customers">
    <Field name="customer0" component={Input} placeholder="customer name" />
    <Field name="customer1" component={Input} placeholder="customer name" />
    <Field name="customer2" component={Input} placeholder="customer name" />
  </FieldArray>
  <Field label="日期:" name="date" component={DatePicker} />
  <Field label="">
    <Button htmlType="submit">Submit</Button>
  </Field>
</Form>

formCore API

formCore 会暴露一些 API,使用这些 API 可以获取、设置表单的数据、状态等。

  • getFieldValue(name):获取某一 Field 的值
  • setFieldValue(name, value):设置某一 Field 的值
  • getValues():获取表单的 values
  • setValues(values, runEffects):设置表单的 values,runEffects 为 Boolean,表示设置 values 之后是否需要执行表单的 effects,默认 false
  • getFieldError(name):获取某一 Field 的 error 信息
  • setFieldError(name, errMsg):设置某一 Field 的 error 信息
  • getErrors():获取所有 Field 的 error 信息
  • setErrors(errors):设置某些 Field 的 error 信息
  • getFieldProps(name):获取某一 Field 的属性值
  • setFieldProps(name, prop):设置某一 Field 的属性值
  • submit():提交表单
  • reset(initialValues):重置表单值为表单初始化时的默认值,如果表单初始化时没有默认值,则清空表单;如果传了参数 initialValues,则 initialValues 会成为新的表单默认值

也可以通过属性的方式获取到一些数据:

  • formCore.values:获取表单的所有值
  • formCore.errors:获取表单校验的错误信息
  • formCore.pristine:表单当前的 values 是否与 initialValues 相等

延伸阅读

开发 @ice/form 表单背景

对于前端,表单开发是一件特别繁琐的事情,尤其在中后台业务中,大家常常会被各种五花八门的表单折磨,又不得不面对现实地去寻找最佳方案,但最终都会发现过度设计的表单组件性能不好,使用简单的表单组件还是需要写大量的业务代码。经过长期的积累以及在社区的调研,我们开发了一个表单组件帮助大家快速地创建一个高性能表单。

组件特性

  • 内部几乎无依赖,体积小
  • 内部管理表单状态,提升开发效率
  • 使用观察者模式提升表单性能
  • 强大的校验以及声明式联动
  • 可结合第三方组件库(Next、Antd)
  • 可自定义 Field

架构方案

npm.io

如上图所示,整个表单的数据都放在 FormCore 这一层,同时 FormCore 会暴露一些 API,以便获取、设置、处理数据。Form、Field 组件通过 Sub/Pub 模式与 FormCore 通信,FormCore 通知组件何时重新渲染。表单提供了校验、联动以及结合 Fusion、Antd 三方组件库使用等能力。

竞品对比

NoForm

NoForm 是一个表单操作(比如说校验、提交、联动等)抽象到上层,下层又包装了 Next、Antd 等组件,UI 上的能力较强,也封装了一些常用的布局,但功能能力较弱,用户实现复杂逻辑还是需要写很多代码。

Formikreact-final-form

这两个组件有一些共性,都是通过 render props 的方式实现了复杂的状态管理,在性能上也非常地卓越,在社区得到了大量的好评,但在联动上的能力较弱(目前只能更新 value),而且如果要集成 Next 或者 Antd 需要将库的表单组件都封装成 Field,成本较高。

相关链接

0.1.7

5 years ago

0.1.6

5 years ago

0.1.5

5 years ago

0.1.5-0

5 years ago

0.1.4

5 years ago

0.1.4-0

5 years ago

0.1.3

5 years ago

0.1.3-0

5 years ago

0.1.2

5 years ago

0.1.2-2

5 years ago

0.1.2-1

5 years ago

0.1.2-0

5 years ago

0.1.1

5 years ago

0.1.0

5 years ago

0.1.0-8

5 years ago

0.1.0-7

5 years ago

0.1.0-6

5 years ago

0.1.0-5

5 years ago

0.1.0-4

5 years ago

0.1.0-3

5 years ago

0.1.0-2

5 years ago

0.1.0-1

5 years ago

0.1.0-0

5 years ago