Repository navigation
cn hx components WithCheck
验证 HOC 和独立消息组件。通过自定义 handle 函数对模型数据做校验,由响应式字段监听触发。
将任意响应式组件包装为带验证的版本。内部通过 ERO.on() 订阅字段变更,当被监听的字段变化时调用 handle 函数,将结果作为错误/警告消息显示在被包装组件的下方。
import { HxWithCheck } from '@hx/components';
// 包装组件
const ValidatedInput = HxWithCheck(HxInput);
<ValidatedInput
$model={form}
$field="email"
$check={{
handle: (event, model) => {
const v = model.email;
if (!v) return '请输入邮箱';
if (!/^[^\s@]+@[^\s@]+$/.test(v)) return '邮箱格式不正确';
return undefined; // 校验通过
},
}}
/>| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
$model |
HxObject<T> |
— | 响应式模型 |
$check |
DynamicCheck | DynamicCheck[] |
— | 一条或多条验证规则,见下方 DynamicCheck |
alwaysKeepMessageDOM |
boolean |
false |
始终渲染消息 DOM 元素,防止布局抖动 |
$domCheckBox |
HTML 属性 | — | 包装 <div> 上的额外属性 |
$domCheckMsg |
HTML 属性 | — | 消息 <span> 上的额外属性 |
被包装组件的全部 prop 同样可用,并原样透传给被包装组件。$visible、$disabled、$readonly 由 HOC 自己解析(支持与其他组件一致的布尔、函数、监听对象三种写法),再把解析后的布尔值向下传递,因此被包装组件与包装 <div> 的状态始终一致。布局类 prop(fGrow、fAlignSelf、gCol、gRows、gAlignSelf、gJustifySelf)由包装 <div> 消费而不是被包装组件,解析后的 data-hx-visible、data-hx-disabled、data-hx-readonly 会与之一并写到包装 <div data-hx-with-check=""> 上,方便从外部为其写样式。
interface DynamicCheck<T extends object> {
on?: string | string[]; // 要监听的字段路径
handle: MonitorCheckFunc<T>; // 校验函数
}
type MonitorCheckFunc<T> = (
event: ValueChangedEvent, // 触发校验的变更事件
model: HxObject<T>, // 响应式模型
context: HxContext // 组件上下文
) => CheckResult;
type CheckResult =
| undefined // 通过——无错误
| string // 错误消息(红色)
| { level: 'warn' | 'error'; message: ReactNode }; // 带级别的消息-
on:要监听的模型字段路径。不指定时,HOC 使用创建时传入的$supplyOn(通常是被包装组件的$field)。两者都不提供则校验永远不会触发。 -
handle:监听的字段变化时被调用。返回undefined表示通过,string表示错误消息,{ level, message }支持警告(黄色)或错误(红色)两种级别。
// 单字段校验(省略 `on`——使用组件的 $field)
<ValidatedInput
$model={form}
$field="email"
$check={{
handle: (event, model) => {
if (!model.email) return '必填';
return undefined;
},
}}
/>
// 多字段关联校验(显式指定 `on`)
<ValidatedInput
$model={form}
$field="confirmPassword"
$check={{
on: ['password', 'confirmPassword'],
handle: (event, model) => {
if (model.password !== model.confirmPassword) return '两次密码不一致';
return undefined;
},
}}
/>
// 同一字段多条校验
<ValidatedInput
$model={form}
$field="username"
$check={[
{
handle: (event, model) => model.username ? undefined : '用户名必填',
},
{
handle: (event, model) => {
if (model.username && model.username.length < 3) return '至少 3 个字符';
return undefined;
},
},
]}
/>
// 警告级别消息(黄色,非阻断)
$check={{
handle: (event, model) => {
if (model.stock < 10) return { level: 'warn', message: '库存不足' };
return undefined;
},
}}为 true 时,消息 DOM 始终存在(无错误时显示空文本),防止校验消息出现/消失导致的布局抖动:
<ValidatedInput
$model={form} $field="email"
$check={{ handle: validateEmail }}
alwaysKeepMessageDOM
/>独立的验证消息展示——适用于消息需要与输入框分离显示,或要进行不绑定单一输入框的跨字段校验。
<HxCheckMessage
$model={form}
$check={{
on: ['password', 'confirmPassword'],
handle: (event, model) => {
if (model.password !== model.confirmPassword) return '两次密码不一致';
return undefined;
},
}}
$checkProps={{}}
$supplyOn={() => ['password', 'confirmPassword']}
/>| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
$model |
HxObject<T> |
— | 响应式模型 |
$check |
DynamicCheck | DynamicCheck[] |
— | 验证规则 |
$checkProps |
P |
— | 传递给 $supplyOn 的 props |
$supplyOn |
(props: P) => string | string[] |
— | 返回监听的字段路径;作为未指定 on 的校验的默认监听路径 |
alwaysKeepMessageDOM |
boolean |
false |
始终渲染消息 DOM |
每个通过 HxWithCheck(BaseComponent) 创建,接受基础组件所有 props 外加 $check、alwaysKeepMessageDOM、$domCheckBox、$domCheckMsg:
| 组件 | 基础组件 |
|---|---|
HxWithCheckInput |
HxInput |
HxWithCheckFormatInput |
HxFormatInput |
HxWithCheckTextarea |
HxTextarea |
HxWithCheckSelect |
HxSelect |
HxWithCheckCheckbox |
HxCheckbox |
HxWithCheckRadio |
HxRadio |
HxWithCheckMCheckbox |
HxMCheckbox |
HxWithCheckMRadio |
HxMRadio |
HxWithCheckUpload |
HxUpload |
import { HxWithCheck } from '@hx/components';
// 可选:提供 $supplyOn 告诉 HOC 默认监听哪些字段
const ValidatedCustom = HxWithCheck(MyComponent, {
$supplyOn: (props) => props.$field, // 默认监听组件自身的 $field
});提供 $supplyOn 后,任何省略 on 的 DynamicCheck 将使用此路径作为监听路径。这就是 HxWithCheckInput 的工作方式——on 由 $field 自动推断。
import { configHxWithCheck } from '@hx/components';
configHxWithCheck({ alwaysKeepMessageDOM: false });- Overview
- Common Concepts
- I18n
- Data Attributes
- Form Components
- Layout Components
- Display Components
- Overlay Components
- Structure Components
- Validation
- Hooks
- Utilities