ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Formily 中 Input 组件的三种接入方式与源码解析:从 Schema 到 React 字段绑定的完整实践

Formily 中 Input 组件的三种接入方式与源码解析:从 Schema 到 React 字段绑定的完整实践 Formily 中 Input 组件的三种接入方式与源码解析从 Schema 到 React 字段绑定的完整实践【免费下载链接】formily Cross Device High Performance Normal Form/Dynamic(JSON Schema) Form/Form Builder -- Support React/React Native/Vue 2/Vue 3项目地址: https://gitcode.com/gh_mirrors/fo/formily本文以 packages/antd/docs/components/Input.md 为骨架系统讲解 Formily 2.x 中formily/antd的Input组件如何通过 Markup Schema、JSON Schema 与纯 JSX 三种方式接入表单并结合 输入组件源码 与 connect 连接器 剖析其字段状态映射、loading/validating 自动提示与只读态readPretty预览的底层实现。读完本文你将掌握在 Formily Ant Design 项目中快速落地单行输入框与多行文本框并能解释其内部工作机制。一、组件定位与文档速览Input是formily/antd表单组件库中最基础的文本输入组件对应 Ant Design 的Input与Input.TextArea。官方文档 Input.md 用一段引言Text input box和三组完整的可运行示例分别演示了 Formily 三种主流接入范式Markup Schema 示例使用createSchemaField生成SchemaField以 JSX 内嵌 Schema 的方式声明字段JSON Schema 示例将 Schema 以纯 JSON 对象形式传入SchemaField纯 JSX 示例不使用 Schema直接用Field组件组合decorator与component。三种方式的共同点是都依赖formily/core的createForm创建表单实例、formily/react的FormProvider提供上下文并配合FormItem装饰器、FormButtonGroup按钮组与Submit提交按钮完成一个可提交的完整表单。从源码结构看formily/antd在 入口文件 中统一导出了input模块因此可以直接通过import { Input } from formily/antd使用。二、方式一Markup Schema 声明式接入Markup Schema 是 Formily 推荐的开发范式Schema 以 JSX 形式直接内联在组件树中类型安全且可读性强。2.1 基础搭建首先创建 Schema 字段渲染器并把Input与FormItem注册到组件表中import React from react import { Input, FormItem, FormButtonGroup, Submit } from formily/antd import { createForm } from formily/core import { FormProvider, createSchemaField } from formily/react const SchemaField createSchemaField({ components: { Input, FormItem, }, }) const form createForm()createSchemaField返回的SchemaField组件会把components中注册的组件名与 Schema 中的x-component、x-decorator字符串建立映射这是所有 Schema 示例都依赖的注册机制。2.2 声明单行输入框与多行文本框export default () ( FormProvider form{form} SchemaField SchemaField.String nameinput titleinput box x-decoratorFormItem x-componentInput required x-component-props{{ style: { width: 240, }, }} / SchemaField.String nametextarea titletext box x-decoratorFormItem required x-componentInput.TextArea x-component-props{{ style: { width: 400, }, }} / /SchemaField FormButtonGroup Submit onSubmit{console.log}Submit/Submit /FormButtonGroup /FormProvider )要点说明SchemaField.String对应 JSON Schema 的type: string字段类型Input 的值为字符串字段类型天然匹配x-decoratorFormItem指定字段装饰器负责标签、校验错误信息、必填星号等展示x-componentInput与x-componentInput.TextArea分别映射到组件注册表中的Input及其静态属性TextArearequired会转化为字段级必填校验由FormItem渲染出错误提示x-component-props中的属性最终透传给 Ant Design 的Input组件因此style、placeholder、maxLength等 AntD 原生 props 均可用。点击Submit后onSubmit{console.log}会把当前表单的 input 与 textarea 值打印出来。三、方式二JSON Schema 接入当 Schema 需要从服务端下发、由配置中心驱动或持久化存储时可以采用纯 JSON 形式。它和 Markup Schema 描述的是同一套字段结构只是写法不同。import React from react import { Input, FormItem, FormButtonGroup, Submit } from formily/antd import { createForm } from formily/core import { FormProvider, createSchemaField } from formily/react const SchemaField createSchemaField({ components: { Input, FormItem, }, }) const form createForm() const schema { type: object, properties: { input: { type: string, title: input box, x-decorator: FormItem, x-component: Input, x-component-props: { style: { width: 240, }, }, }, textarea: { type: string, title: input box, x-decorator: FormItem, x-component: Input.TextArea, x-component-props: { style: { width: 240, }, }, }, }, } export default () ( FormProvider form{form} SchemaField schema{schema} / FormButtonGroup Submit onSubmit{console.log}Submit/Submit /FormButtonGroup /FormProvider )与 Markup Schema 的差异仅在传参形式上Markup 写法把 Schema 写在SchemaField的子节点中JSON 写法则整体作为schemaprop 传入properties下每个键即字段路径。x-component字符串同样依赖createSchemaField的注册表完成组件解析。四、方式三纯 JSX 接入无 Schema在不需要 Schema 驱动的简单场景下可以直接使用formily/react的Field组件以数组形式声明decorator装饰器与component组件及其 props。import React from react import { Input, FormItem, FormButtonGroup, Submit } from formily/antd import { createForm } from formily/core import { FormProvider, Field } from formily/react const form createForm() export default () ( FormProvider form{form} Field nameinput titleinput box required decorator{[FormItem]} component{[ Input, { style: { width: 240, }, }, ]} / Field nametextarea titletext box required decorator{[FormItem]} component{[ Input.TextArea, { style: { width: 400, }, }, ]} / FormButtonGroup Submit onSubmit{console.log}Submit/Submit /FormButtonGroup /FormProvider )component数组的第二个元素即组件 props此处透传styledecorator数组同理可携带FormItem的 props。这种写法跳过了createSchemaField注册环节适合在既有 React 组件树中零星接入 Formily 字段。五、源码级原理Input 是如何被「连接」到表单的文档 API 一节仅给出 Ant Design 官方链接Input 的InputProps/TextAreaProps全部透传而formily/antd的Input之所以具备 loading 提示、只读预览等增强能力关键在于 packages/antd/src/input/index.tsx 中对connect的封装。5.1 connect 的职责connect是formily/react提供的组件连接器定义于 packages/react/src/shared/connect.ts。其核心逻辑是把一系列映射器mapper从左到右包裹目标组件最终返回一个forwardRef包装组件并借助hoistNonReactStatics保留 AntD 组件的静态成员export function connectT extends JSXComponent( target: T, ...args: IComponentMapperT[] ) { const Target args.reduce((target, mapper) { return mapper(target) }, target) // ...forwardRef 包装 hoistNonReactStatics }formily/antd的Input正是由AntdInput依次经过两个映射器得到export const Input: ComposedInput connect( AntdInput, mapProps((props, field) { return { ...props, suffix: ( span {field?.[loading] || field?.[validating] ? ( LoadingOutlined / ) : ( props.suffix )} /span ), } }), mapReadPretty(PreviewText.Input) )5.2 字段状态自动映射loading / validating 图标mapProps接收一个回调(props, field) props每次渲染时都能拿到当前字段实例field并重写传给 AntD Input 的 props。这里的增强点是suffix 插槽当字段处于field.loading如异步远程请求或field.validating如异步校验进行中时在输入框尾部渲染LoadingOutlined旋转图标否则回退为原始props.suffix不影响用户自定义后缀。loading与validating是formily/core字段模型的内置可观察状态见 packages/core/src/models/Field.ts分别对应setLoading与setValidating方法并在字段状态中参与validating阶段判断。Formily 的Submit组件在提交时同样基于这些状态做节流与反馈因此输入框的旋转图标与提交按钮的 loading 会保持语义一致。5.3 只读态预览mapReadPretty PreviewText.InputmapReadPretty(PreviewText.Input)是第二个映射器其实现位于 connect.ts当字段的pattern readPretty只读模式时不再渲染真实的 AntD Input而是渲染PreviewText.Input纯文本展示组件否则渲染原始目标组件。PreviewText.Input定义于 packages/antd/src/preview-text/index.tsx它用Space把addonBefore、prefix、值文本、suffix、addonAfter依次排开值通过usePlaceholder兜底值合法且非空字符串时显示原值否则显示占位符默认占位符为N/A可通过PreviewText.PlaceholderPlaceholderContext.Provider在表单树外层统一修改。Input.TextArea同样通过connect(AntdInput.TextArea, mapReadPretty(PreviewText.Input))包装只读态复用同一套纯文本预览。5.4 组合类型声明源码用ComposedInput交叉类型声明了Input的复合形态——既是一个接收InputProps的 React 组件又附带静态成员TextArea接收TextAreaPropstype ComposedInput React.FCReact.PropsWithChildrenInputProps { TextArea?: React.FCReact.PropsWithChildrenTextAreaProps }这解释了为何x-componentInput.TextArea和component{[Input.TextArea, props]}两种引用方式都能成立TextArea是挂在Input上的静态组件。六、API 与属性透传说明formily/antd的Input完整继承 Ant DesignInput的全部属性InputPropsInput.TextArea则继承TextAreaProps包括但不限于placeholder、value、defaultValue、onChangemaxLength、allowClear、disabled、readOnlyprefix/suffix/addonBefore/addonAfter其中suffix在字段 loading/validating 时会被内置图标接管见 5.2 节sizelarge/middle/small、bordered、showCount等。由于组件通过connect与 Formily 字段打通value与onChange无需手动维护——字段值由 Formily 双向绑定管理required等字段校验属性则由FormItem装饰器配合formily/core校验引擎packages/validator统一处理。具体组件可用属性以 Ant Design 官方 Input 文档为准本仓库侧仅透传不改写。七、三种方式的选型建议接入方式适用场景核心代码位置Markup Schema常规业务表单Schema 内嵌在组件树类型友好文档「Markup Schema example」一节JSON SchemaSchema 来自服务端 / 配置驱动 / 需要序列化存储文档「JSON Schema case」一节纯 JSX简单表单、局部接入不引入 Schema 概念文档「Pure JSX case」一节三者最终都归一到 Formily 的字段模型中因此formily/core的联动effects/reactions、校验、值变化订阅等能力完全一致切换接入方式不会改变字段语义。如果你需要更完整的表单布局能力可继续阅读 FormItem 文档、FormLayout 文档 或参考 输入框验证码场景示例。【免费下载链接】formily Cross Device High Performance Normal Form/Dynamic(JSON Schema) Form/Form Builder -- Support React/React Native/Vue 2/Vue 3项目地址: https://gitcode.com/gh_mirrors/fo/formily创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表