Field组件
如果您想要对字段进行更精细的控制,则推荐使用Field
组件。Field
组件是创建表单自定义字段组件的终极武器,允许您完全控制字段的渲染、校验、可视、使能等等,并且所有字段特性属性均可以使用计算属性声明,这使用Field
组件具有超强的自定义能力,还可以很轻松地实现表单字段之间的联动。
创建字段
使用Field
组件创建一个字段。
<Field
name="user.firstName"
render={
({name, value, bind }) => {
return <input {...bind} />
}
}
/>
Field
组件至少要求提供name
和render
两个属性。
name
: 指向的是状态树中的某个字段的路径,如user.firstName
。render
: 用于渲染Field
组件,它接收一个AutoFieldRenderProps
类型的参数,负责渲染Field
组件。
简单的Field
组件示例:
字段校验
Field
组件支持validate
属性用于配置字段的校验规则。
基本校验
<Field
validate={(value)=>{
return assert(value.length>3,"长度必须大于3")
}}
//...
/>
validate
该属性的值用于创建一个依赖于当前字段(name指向的状态)状态的计算或监听属性,并且其scope
也指向当前字段的值。 当字段值发生变化时,会重新计算该属性的值,从而会触发校验。validate
计算函数返回true/false
来代表校验是否通过。也可以throw Error
,然后通过错误对象的message
属性来获取错误信息并传递给render
函数。
<Field
validate={(value)=>{
return assert(value.length>3,"长度必须大于3")
}}
render={
({ name,
value,
error, // 校验错误信息
validate, // 校验结果true/false
bind
}) => {
return (
<div>
<input {...bind} />
{validate ? '校验合法' : '校验不合法'}
{error ? <span>{error.message}</span> : null}
</div>
)
}
}
/>
validate
是一个同步计算属性,依赖于当前字段的值,当字段值发生变化时,会重新计算该属性的值,从而会触发校验。
联动校验
正因为validate
是一个同步计算属性,所以也可以依赖于其他字段的值,从而实现字段之间的联动校验。
在上例中,count
的校验规则是count>0 && order.price > 9
,由于其validate
是同步计算属性,根据计算属性的依赖收集规则,其自动依赖于order.price
和count
的值,所以当count
和order.price
更新时会触发validate
属性重新计算,从而触发校验。
提示
validate
属性是一个同步计算属性,具备依赖自动收集功能,当字段值发生变化时,会重新计算该属性的值,从而会触发校验。
字段计算属性
除了validate
属性,则字段组件还支持以下常用的计算属性:
属性 | 类型 | 默认值 | 计算属性 | 说明 |
---|---|---|---|---|
required | boolean | false | 同步 | 是否必填 |
visible | boolean | true | 同步 | 是否可见 |
enable | boolean | true | 同步 | 是否可用 |
readonly | boolean | false | 同步 | 是否只读 |
label | string | - | 同步 | 字段标签 |
placeholder | string | - | 同步 | 字段占位符 |
help | string | - | 同步 | 字段帮助信息 |
select | any[] | - | 异步 | 字段选择项 |
以上这些属性都是同步计算属性,当字段值发生变化时,会重新计算该属性的值,从而会触发字段的重新渲染。同时也支持计算属性的相关特性。
以上这些属性会在更新时触发字段的重新渲染,并传递给字段组件的render
函数。
<Field
name="user.firstName"
required={(state)=>{ ... }}
visible={(state)=>{ ... }}
enable={(state)=>{ ... }}
readonly={(state)=>{ ... }}
label={(state)=>{ ... }}
placeholder={(state)=>{ ... }}
help={(state)=>{ ... }}
select={async (state)=>{ ... }}
render={
({name, value, bind, required, visible, enable, readonly, label, placeholder, help, select }) => {
return (
<div>
{/* ... */}
</div>
)
}
}
/>
异步字段计算属性
以上的计算属性除了select
外,其他均是同步计算属性,当字段值发生变化时,会重新计算该属性的值,从而会触发字段的重新渲染。
但是有时候我们需要的计算属性是异步的,如我们想进行异步校验时,则需要使用useComputed
异步计算属性。
<Field
name="user.firstName"
render={
({name, value, bind }) => {
const valid = useComputed<boolean>(async (name:string)=>{
await delay(1000) // 模拟异步验证
return assert(name.length>3,"name长度必须大于3")
},{
depends:["user.name"],
scope:'user.name',
onError:()=>false
})
return (
<div>
{/* ... */}
</div>
)
}
}
/>
useComputed
用于动态创建一个异步计算属性。- 上例中,指定了
useComputed
的depends=["user.name"]
和scope:'user.name
,代表了其依赖于user.name
的值,当user.name
更新时,会重新计算该属性的值。并且useComputed
的scope
也指向user.name
的值。 - 当校验失败时不是只返回
false
,而是触发错误,通过error.message
来错误信息。 - 指定
onError:()=>false
的目的是当校验失败时,将计算值重置为false
。
实际示例如下:
配置onError:()=>false
的原因?
计算属性具有一个onError
回调函数,用于处理计算属性的错误,当计算属性发生错误时,会触发onError
回调函数,onError
的返回值会被作为计算结果写入。