news 2026/9/23 19:15:33

Formily Next NumberPicker 数字输入组件实战指南:三种 Schema 用法与源码机制解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Formily Next NumberPicker 数字输入组件实战指南:三种 Schema 用法与源码机制解析
  • 前端
  • UI组件

【免费下载链接】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
点击查看免费下载

NumberPicker 是 Formily 基于 Fusion Design(@alifd/next)数字输入框封装的高阶表单组件,用于数字类型的录入、步进调节与范围约束。本文以 @formily/next 包中的 NumberPicker 组件为核心,完整演示 Markup Schema、JSON Schema、Pure JSX 三种接入方式的实战代码,并深入 connect 源码揭示其字段状态映射(size/status)、只读预览(readPretty)与 FormLayout 尺寸联动的底层机制,帮助你在 Formily 表单体系中正确、高效地使用数字输入组件。

一、组件定位与适用场景

NumberPicker 在 Formily 中承担"数字输入框"的角色,位于@formily/next包内。它并非从零实现的组件,而是对阿里 Fusion Design 的NumberPicker@alifd/next)进行的协议化封装:通过@formily/reactconnect高阶能力,把表单字段的校验状态、尺寸、只读态等自动映射到 Fusion 数字输入框上。

它适合以下典型场景:

  • 数量、金额、年龄、价格等纯数字字段录入;
  • 需要步进器(上/下箭头)微调数值;
  • 需要限定最小值、最大值、整数位/小数位精度
  • 详情展示场景下以只读预览形式回显数字。

从源码看,NumberPicker 的完整实现在 number-picker/index.tsx,核心只有几行:

import { connect, mapProps, mapReadPretty } from '@formily/react' import { NumberPicker as InputNumber } from '@alifd/next' import { PreviewText } from '../preview-text' import { mapSize, mapStatus } from '../__builtins__' export const NumberPicker = connect( InputNumber, mapProps(mapSize, mapStatus), mapReadPretty(PreviewText.NumberPicker) ) export default NumberPicker

可以看到:底层输入框来自@alifd/next,接入字段后由mapProps(mapSize, mapStatus)自动注入尺寸与状态,由mapReadPretty(PreviewText.NumberPicker)接管只读预览渲染。组件样式通过 style.ts 引入@alifd/next/lib/number-picker/style,并通过@formily/next的 src/index.ts 统一对外导出。

二、三种接入方式完整示例

Formily 支持三种形态书写同一个表单,下面三个示例完全等价,均实现一个宽度 240 的必填数字输入框,并配套提交按钮。

2.1 Markup Schema 方式(JSX 语法糖)

Markup Schema 用 JSX 标签直接描述 Schema,可读性最好、最接近普通 JSX 开发习惯:

import React from 'react' import { NumberPicker, FormItem, FormButtonGroup, Submit } from '@formily/next' import { createForm } from '@formily/core' import { FormProvider, createSchemaField } from '@formily/react' const SchemaField = createSchemaField({ components: { NumberPicker, FormItem, }, }) const form = createForm() export default () => ( <FormProvider form={form}> <SchemaField> <SchemaField.String name="input" title="input box" x-decorator="FormItem" x-component="NumberPicker" required x-component-props={{ style: { width: 240, }, }} /> </SchemaField> <FormButtonGroup> <Submit onSubmit={console.log}>Submit</Submit> </FormButtonGroup> </FormProvider> )

要点说明:

  • createSchemaField注册的组件表中同时包含NumberPickerFormItemx-decorator负责布局/校验信息展示,x-component负责实际输入控件;
  • required声明必填,配合FormItem会在未填写时展示校验错误;
  • x-component-props中的 props 会透传给 NumberPicker 底层组件(此处传入style.width)。

2.2 JSON Schema 方式(纯数据驱动)

JSON Schema 将描述与 UI 彻底解耦,适合由后端下发或动态配置的场景,写法与 Markup Schema 一一对应:

import React from 'react' import { NumberPicker, FormItem, FormButtonGroup, Submit } from '@formily/next' import { createForm } from '@formily/core' import { FormProvider, createSchemaField } from '@formily/react' const SchemaField = createSchemaField({ components: { NumberPicker, FormItem, }, }) const form = createForm() const schema = { type: 'object', properties: { input: { type: 'string', title: 'input box', 'x-decorator': 'FormItem', 'x-component': 'NumberPicker', '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 的对应关系:<SchemaField.String name="input">等价于properties.inputx-decoratorx-componentx-component-props三个字段名在 JSON 中改为字符串键。注意此处 Schema 的type: 'string'仅描述字段类型,NumberPicker 实际输入/输出的仍是数字值。

2.3 Pure JSX 方式(不使用 Schema)

如果不使用 Schema 体系,可以直接用@formily/reactField组件命令式声明:

import React from 'react' import { NumberPicker, FormItem, FormButtonGroup, Submit } from '@formily/next' import { createForm } from '@formily/core' import { FormProvider, Field } from '@formily/react' const form = createForm() export default () => ( <FormProvider form={form}> <Field name="input" title="input box" required decorator={[FormItem]} component={[ NumberPicker, { style: { width: 240, }, }, ]} /> <FormButtonGroup> <Submit onSubmit={console.log}>Submit</Submit> </FormButtonGroup> </FormProvider> )

三种方式的取舍建议:

方式特点适合场景
Markup SchemaJSX 即 Schema,类型提示友好前端直接书写表单的常规开发
JSON Schema纯数据描述,可序列化/动态下发低代码、配置化、服务端驱动表单
Pure JSX跳过 Schema 解析,直连 Field追求最小依赖、复杂联动逻辑

无论哪种方式,<Submit onSubmit={console.log}>都会在提交时把表单值(含input字段)打印到控制台,可直接观察 NumberPicker 的取值结果。

三、源码机制:connect 如何让 Fusion 输入框接入 Formily 字段

理解了用法后,有必要看一下connect的底层机制,这能解释"为什么写一个 NumberPicker 标签就能自动拿到校验状态、尺寸和只读能力"。

connect定义在 packages/react/src/shared/connect.ts,其核心实现为:把传入的mapPropsmapReadPretty等映射器(mapper)依次作用于目标组件,最终包装成一个React.forwardRef组件。其中两个关键映射器:

1.mapProps(mapSize, mapStatus)—— 状态与尺寸自动注入

  • mapSize(packages/next/src/builtins/mapSize.ts):读取FormLayout上下文中的size配置。若布局未指定 size,则使用FormLayout的默认值(源码中'default'会被归一化为 Fusion 的'medium')。这意味着只要在表单外层配置了FormLayout size,所有 NumberPicker 都会自动跟随该尺寸,无需逐个设置。
  • mapStatus(packages/next/src/builtins/mapStatus.ts):根据字段状态推导 Fusion 输入框的state属性——字段loading/validating时映射为loading,存在selfErrors时映射为error,存在selfWarnings时映射为warning,否则回退到decoratorProps.feedbackStatus。这就是"校验失败时输入框自动变红"的原理。

2.mapReadPretty(PreviewText.NumberPicker)—— 只读预览

mapReadPretty逻辑同样在 connect.ts 中:当字段pattern === 'readPretty'(只读模式)时,不再渲染 Fusion 输入框,而是渲染PreviewText.NumberPicker。该组件定义在 packages/next/src/preview-text/index.tsx,实现为:

const NumberPicker: React.FC<React.PropsWithChildren<NumberPickerProps>> = ( props ) => { return <NextNumberPicker {...props} isPreview /> }

它复用了 Fusion NumberPicker 的isPreview能力,将数字值以纯文本形式展示。这意味着当表单进入详情/查看模式(如form.setPattern('readPretty'))时,NumberPicker 会自动从可输入态切换为纯文本回显,无需任何额外代码。

四、常用配置参数(API)

NumberPicker 的完整 API 对齐 Fusion Design 的数字输入框,可通过x-component-props(Schema 方式)或组件 props(JSX 方式)传入。以下为最常用的配置项:

参数类型默认值说明
valuenumber-当前值(由 Formily 字段自动注入,一般无需手动传)
defaultValuenumber-非受控模式下的初始值
onChange(value: number) => void-值变化回调(Formily 会自动接管该事件写入字段)
minnumber-允许的最小值
maxnumber-允许的最大值
stepnumber1步长,点击步进器时每次增减的值
precisionnumber-小数精度(保留的小数位数)
size'large' \| 'medium' \| 'small'跟随 FormLayout输入框尺寸
disabledbooleanfalse禁用输入
styleCSSProperties-内联样式(如宽度)

典型配置示例(限制 0~100、步长 5、保留整数):

<SchemaField.String name="score" title="评分" x-component="NumberPicker" required x-component-props={{ min: 0, max: 100, step: 5, precision: 0, style: { width: 200 }, }} />

注意:size参数通常无需手动指定——如源码所示,NumberPicker 会从FormLayout上下文自动继承,手动传入的size优先级更高(props.size || takeSize())。同样的,state(loading/error/warning)也由mapStatus根据字段校验结果自动推导。

五、与 FormItem 的协作

在 Formily 体系中 NumberPicker 必须搭配FormItem(作为x-decorator)才能获得完整的表单能力:

  • 校验反馈requiredvalidator等校验结果通过mapStatus映射为 Fusion 输入框的error/warning状态,同时FormItem负责渲染错误文案;
  • 布局控制FormItem负责 label、帮助文案、错误信息的排版,style.width等样式配置作用于输入框本身;
  • 只读切换FormItemmapReadPretty协同,在readPretty模式下将整个字段切换为纯文本展示。

因此,三处示例中的components: { NumberPicker, FormItem }注册缺一不可——FormItemx-decorator="FormItem"引用,NumberPickerx-component="NumberPicker"引用。

六、环境与依赖前提

使用@formily/next的 NumberPicker 需要满足以下前提(依据 packages/next/package.json):

  • peerDependencies@alifd/next(^1.19.0)、react/react-dom/react-is(>=16.8.0,Hook 版本要求);
  • 依赖包@formily/core@formily/react@formily/reactive@formily/json-schema等均为同版本 2.3.7;
  • 样式:组件样式通过 style.ts 引入@alifd/next/lib/number-picker/style,构建时由create-style/build-style脚本处理。

安装后即可按上文三种方式使用;若只需展示数字而不希望用户编辑,可配合FormLayout的只读模式或直接使用PreviewText组件。

七、小结

NumberPicker 是 Formily Next 表单体系中"麻雀虽小、五脏俱全"的典型组件:使用层面,它支持 Markup Schema、JSON Schema、Pure JSX 三种等价写法;机制层面,connect+mapProps(mapSize, mapStatus)+mapReadPretty(PreviewText.NumberPicker)的组合让它在零配置下自动获得尺寸跟随、校验状态反馈与只读预览能力。掌握这一个组件,即可举一反三地理解@formily/next中其余所有 Schema 组件的封装模式。

  • 前端
  • UI组件

【免费下载链接】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
点击查看免费下载
上一篇:告别Lua代码隐患:xLua单元测试框架实战指南
下一篇:React DevTools单元测试指南:确保扩展功能稳定性

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/23 19:14:53

高级人工智能训练师实战:从数据工程到模型评测的完整路径

简介&#xff1a;《高级人工智能训练师》是一份聚焦店小蜜智能客服配置优化的PDF学习资料&#xff0c;面向电商客服主管、AI训练师及店铺运营人员&#xff0c;尤其适合准备高级人工智能训练师认证或正为店小蜜后台调优发愁的读者。资源包共1个PDF文件&#xff0c;容量仅861KB&a…

作者头像 李华
网站建设 2026/9/23 19:06:20

GPT-OSS框架:实现AI可控性的双引擎架构解析

1. 项目背景与核心价值去年在参加某头部科技企业的技术闭门会时&#xff0c;有个场景让我印象深刻&#xff1a;当工程师演示完最新的大模型应用后&#xff0c;企业CTO直接发问&#xff1a;"这个系统如果部署在产线上&#xff0c;失控风险怎么控制&#xff1f;误操作损失谁…

作者头像 李华
网站建设 2026/9/23 19:02:43

电脑声音太小?Cool Edit录音增强与音频后期处理全攻略

上周有个粉丝私信我&#xff0c;说想用 Cool Edit 录一首歌&#xff0c;结果折腾了两天&#xff0c;录进去的声音比蚊子叫还小&#xff0c;电脑本身放歌也总觉得差口气。我问他麦克风增益开了没&#xff0c;他反问我"什么是增益"。这个对话我见过太多次了——多数人下…

作者头像 李华