十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

Formily Next 日期选择器(DatePicker)实战指南:三种 Schema 写法与 Moment 值转换原理

Formily Next 日期选择器(DatePicker)实战指南:三种 Schema 写法与 Moment 值转换原理 前端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点击查看免费下载导读本文围绕formily/next中的日期选择器组件DatePicker展开系统讲解其在 Formily 表单体系中的三种接入方式Markup Schema、JSON Schema、Pure JSX、五种内置形态普通日期、周选择、月选择、年选择、范围选择以及与FormItem装饰器、只读态PreviewText的配合。读完本文你将掌握在 Formily 项目中快速落地各种日期选择场景的完整套路并理解组件底层基于 moment 的「值格式自动转换」机制从而避免表单值与展示格式不一致的常见坑。组件定位基于 Fusion Next 的 Formily 化封装packages/next是 Formily 面向阿里 Fusion Designalifd/next体系的高阶组件包。其中的 DatePicker 源码 并非从零实现一个日期控件而是通过formily/react提供的connect能力将 Fusion 的DatePicker桥接到 Formily 的字段模型中export const DatePicker: ComposedDatePicker connect( NextDatePicker, mapProps(mapDateFormat(), mapSize, mapStatus), mapReadPretty(PreviewText.DatePicker) )核心套路可拆解为三层connect把受控组件与 Formily 的Field绑定实现 value/onChange 的自动接管mapProps把 Formily 字段状态尺寸、校验状态与组件的 props 做映射并注入日期格式转换逻辑mapReadPretty为组件挂载只读态渲染即字段处于pattern readPretty时自动退化为PreviewText。DatePicker同时以复合组件形式挂载了四个子组件见 index.tsx#L80-L102子组件对应 Fusion 组件默认提交格式DatePicker.WeekPickerWeekPickerYYYY-woDatePicker.MonthPickerMonthPickerYYYY-MMDatePicker.YearPickerYearPickerYYYYDatePicker.RangePickerRangePickerYYYY-MM-DD起止两个值从源码结构看这些子组件都复用了同一套mapDateFormat与只读映射逻辑因此在使用方式上与主组件完全一致只是格式与交互不同。三种接入方式完整示例方式一Markup SchemaJSX 描述式Markup Schema 是 Formily 最推荐的写法用 JSX 组件即 Schema 节点类型安全且可读性强import React from react import { DatePicker, FormItem, FormButtonGroup, Submit } from formily/next import { createForm } from formily/core import { FormProvider, createSchemaField } from formily/react const SchemaField createSchemaField({ components: { DatePicker, FormItem, }, }) const form createForm() export default () ( FormProvider form{form} SchemaField SchemaField.String namedate titlenormal date x-decoratorFormItem x-componentDatePicker / SchemaField.String nameweek titleWeek Selection x-decoratorFormItem x-componentDatePicker.WeekPicker / SchemaField.String namemonth titleMonth Selection x-decoratorFormItem x-componentDatePicker.MonthPicker / SchemaField.String nameyear titleYear selection x-decoratorFormItem x-componentDatePicker.YearPicker / SchemaField.String name[startDate,endDate] titleDate Range x-decoratorFormItem x-componentDatePicker.RangePicker x-component-props{{ showTime: true, }} / SchemaField.String namerange_month titleMonth Range Selection x-decoratorFormItem x-componentDatePicker.RangePicker x-component-props{{ type: month, }} / SchemaField.String namerange_year titleYear range selection x-decoratorFormItem x-componentDatePicker.RangePicker x-component-props{{ type: year, }} / /SchemaField FormButtonGroup Submit onSubmit{console.log}Submit/Submit /FormButtonGroup /FormProvider )要点说明字段统一使用SchemaField.String因为表单最终提交的值是字符串x-decoratorFormItem负责布局、标签与校验反馈展示x-componentDatePicker.xxx用点语法引用复合子组件范围选择RangePicker的字段名写成[startDate,endDate]这是 Formily 内置的「范围内置字段」约定表单值将自动聚合成{ startDate, endDate }对象结构x-component-props中的showTime、type等会原样透传给底层组件type支持month | year | week用于让 RangePicker 呈现月区间、年区间。方式二JSON Schema纯数据描述式当 Schema 需要由后端下发、或需要动态拼装时使用 JSON Schema 写法两种写法表达的字段结构完全等价import React from react import { DatePicker, FormItem, FormButtonGroup, Submit } from formily/next import { createForm } from formily/core import { FormProvider, createSchemaField } from formily/react const SchemaField createSchemaField({ components: { DatePicker, FormItem, }, }) const form createForm() const schema { type: object, properties: { date: { title: Normal date, x-decorator: FormItem, x-component: DatePicker, type: string, }, week: { title: Week Selection, x-decorator: FormItem, x-component: DatePicker.WeekPicker, type: string, }, month: { title: Month Selection, x-decorator: FormItem, x-component: DatePicker.MonthPicker, type: string, }, year: { title: Year selection, x-decorator: FormItem, x-component: DatePicker.YearPicker, type: string, }, [startDate,endDate]: { title: Date range, x-decorator: FormItem, x-component: DatePicker.RangePicker, x-component-props: { showTime: true, }, type: string, }, range_month: { title: Month Range Selection, x-decorator: FormItem, x-component: DatePicker.RangePicker, x-component-props: { type: month, }, type: string, }, range_year: { name: range_year, title: Year range selection, x-decorator: FormItem, x-component: DatePicker.RangePicker, x-component-props: { type: year, }, type: string, }, }, } export default () ( FormProvider form{form} SchemaField schema{schema} / FormButtonGroup Submit onSubmit{console.log}Submit/Submit /FormButtonGroup /FormProvider )与 Markup Schema 的差异仅在书写形态JSON Schema 以schema对象驱动SchemaField schema{schema} /而 Markup Schema 以 JSX 子节点驱动。二者在渲染层完全等价可随时互相转换。方式三Pure JSX命令式编程不依赖 Schema 时可以直接用formily/react的Field组件手写字段import React from react import { DatePicker, 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 namedate titledate selection decorator{[FormItem]} component{[DatePicker]} / Field nameweek titleWeek Selection decorator{[FormItem]} component{[DatePicker.WeekPicker]} / Field namequarter titleFinancial Year Selection decorator{[FormItem]} component{[DatePicker.MonthPicker]} / Field nameyear titleYear selection decorator{[FormItem]} component{[DatePicker.YearPicker]} / Field name[startDate,endDate] titleDate range selection decorator{[FormItem]} component{[DatePicker.RangePicker]} / Field namerange_month titleMonth Range Selection decorator{[FormItem]} component{[ DatePicker.RangePicker, { type: month, }, ]} / Field namerange_year titleYear range selection decorator{[FormItem]} component{[ DatePicker.RangePicker, { type: year, }, ]} / FormButtonGroup Submit onSubmit{console.log}Submit/Submit /FormButtonGroup /FormProvider )Pure JSX 的关键差异在于 props 的传递方式decorator{[FormItem]}等价于x-decoratorcomponent{[DatePicker]}等价于x-component而组件参数如type: month需要写成component{[DatePicker.RangePicker, { type: month }]}的二元数组形式。此模式适合逻辑简单、无需 Schema 动态化的场景。三种写法的选型建议维度Markup SchemaJSON SchemaPure JSX类型提示强JSX 即 Schema弱纯对象中动态化能力中强可后端下发弱代码可读性高中高典型场景常规表单开发配置化 / 低代码简单局部字段三者最终都会落到 Formily 的Field模型上交互行为、校验与提交逻辑完全一致可按项目形态自由切换。源码级原理解析Moment 值格式自动转换默认格式映射DatePicker的格式转换由mapDateFormat完成见 date-picker/index.tsx#L35-L72其默认格式规则为场景默认展示/提交格式普通日期YYYY-MM-DDtypemonth/ MonthPickerYYYY-MMtypeyear/ YearPickerYYYYtypeweek/ WeekPickerYYYY-wo开启showTime追加HH:mm:ss可用showTime.format覆盖当显式传入format属性时该属性优先生效showTime会基于日期格式拼接时间格式例如YYYY-MM-DDHH:mm:ss。也就是说表单层拿到并提交的始终是格式化后的字符串而不是 moment 对象——这与SchemaField.String的type: string声明是自洽的。值进出场转换momentable 与 formatMomentValue组件通过两个工具函数完成「字符串 ⇄ moment」的双向转换二者定义在 packages/next/src/builtins/moment.ts入场momentable把表单字符串值转成 moment 实例交给底层控件渲染且兼容数组值范围选择的两个值会逐项转换出场formatMomentValue在 onChange 中把底层回传的 moment 实例按约定格式格式化回字符串若是范围选择会按索引分别格式化后以数组返回。值得注意的一个细节formatMomentValue内部对形如19:55:22的时间字符串做了特判——直接命中^(?:[01]\d|2[0-3]):[0-5]\d(:[0-5]\d)?$时会以format作为第二参数调用 moment从而正确处理纯时间字符串见 moment.ts#L23-L38。状态与尺寸自动映射mapStatusmapStatus.ts会把 Formily 字段的loading、validating、selfErrors、selfWarnings映射为 Fusion 控件需要的state属性实现校验错误自动红框、异步校验自动 loadingmapSizemapSize.ts则会从 FormLayout 上下文读取尺寸并把default归一化为 Fusion 的medium。这意味着日期选择器的外观会随FormLayout全局配置联动无需逐个字段配置。只读态支持PreviewText.DatePicker当字段进入只读场景如详情页、提交回显时mapReadPretty(PreviewText.DatePicker)会让 DatePicker 自动退化为纯文本展示。对应实现见 preview-text/index.tsx#L176-L198const DatePicker: React.FCReact.PropsWithChildrenDatePickerProps ( props ) { const placeholder usePlaceholder() const prefixCls usePrefixCls(form-preview, props) const getLabels () { const labels formatMomentValue(props.value, props.format, placeholder) return isArr(labels) ? labels.join(~) : labels } return div className{cls(prefixCls, props.className)}{getLabels()}/div }单个日期值直接按format格式化输出范围值会以~连接如2024-01-01~2024-01-31空值默认展示占位符N/A可通过PreviewText.Placeholder上下文自定义只读态同样走formatMomentValue因此展示格式与提交格式天然一致不会出现「提交的是YYYY-MM-DD、展示却多出时间」之类的错位。进阶DatePicker2 与季度选择如果项目使用 Fusion 的DatePicker2体系moment 对象二选一之外的新版日期组件formily/next还提供了DatePicker2封装date-picker2/index.tsx。与DatePicker相比DatePicker2额外支持QuarterPicker季度选择默认提交格式为YYYY-\QQ如2024-Q1且showTime场景下默认格式直接合并为YYYY-MM-DD HH:mm:ss。其复合子组件RangePicker/MonthPicker/YearPicker/WeekPicker/QuarterPicker与使用方式与DatePicker完全对齐。另外packages/antd与packages/element分别提供了面向 Ant Design 与 Element 的等价封装接口与本文所述保持一致——如果你在 Vue 或 AntD 生态中迁移可以复用相同的 Schema 结构。API 与后续延伸DatePicker的完整属性 API 与 Fusion 官方DatePicker保持一致即alifd/next的 date-picker 组件属性本文不再赘述。实际开发中如需自定义展示格式、日期禁用范围、国际化等直接通过x-component-props透传对应属性即可Formily 层不会拦截。若需深入了解 Schema 驱动的底层机制可继续阅读字段模型与联动packages/core 文档表单布局与 FormItem 装饰器FormItem.md只读态组件体系PreviewText.mdVue 侧的日期组件方案element DatePicker 指南结合本文的三种接入方式与格式转换原理你可以在 Formily 项目中快速、稳定地实现从「单日期」到「带时间的区间选择」的全部常见业务形态。赞分享前端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点击查看免费下载相关推荐从理论到实践FluvioFX流体动力学求解器工作原理剖析从理论到实践FluvioFX流体动力学求解器工作原理剖析 FluvioFX是一款为Unity VFX Graph打造的流体动力学求解器能够帮助开发者在游戏和前端UI组件如何快速部署Home Assistant操作系统5个简单步骤的完整指南如何快速部署Home Assistant操作系统5个简单步骤的完整指南 Home Assistant操作系统是一款专为智能家居控制中心优化的Linux系统基前端UI组件Formily 级联选择器 Cascader 实战指南Markup Schema / JSON Schema / 纯 JSX 三种写法与异步省市区数据源Formily 级联选择器 Cascader 实战指南Markup Schema / JSON Schema / 纯 JSX 三种写法与异步省市区数据源 本文前端UI组件上一篇终极粒子群优化实战指南用scikit-opt轻松掌握PSO算法核心与调优技巧下一篇RR项目为RS2821RP设备构建定制化系统镜像的技术实践创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表