-
Notifications
You must be signed in to change notification settings - Fork 267
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(form): 多端适配 #2595
base: feat_v3.x
Are you sure you want to change the base?
feat(form): 多端适配 #2595
Conversation
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the Walkthrough本次变更主要涉及多个文件的更新,增强了表单组件的功能和样式。 Changes
Suggested labels
Suggested reviewers
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
Outside diff range and nitpick comments (3)
src/packages/formitem/formitem.scss (1)
68-68
: 建议移除不必要的空行第 68 行的空行是不必要的,建议移除以提高代码的简洁性。
-
src/packages/formitem/formitem.taro.tsx (2)
61-62
: 类型更新很好,但请尝试解决潜在的类型问题。将
context
属性声明更新为使用React.ContextType<typeof Context>
,提供了更好的类型信息。但是,需要使用@ts-ignore
注释来抑制 TypeScript 错误,这表明代码库中可能存在类型不匹配或过时的类型定义。建议调查并解决潜在的类型问题,以消除对忽略注释的需要,提高代码的类型安全性。
268-268
: 请删除调试代码。这行 console log 语句似乎是遗留的调试代码,应该删除。
-console.log('testtest', child)
Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Files ignored due to path filters (1)
packages/nutui-taro-demo/yarn.lock
is excluded by!**/yarn.lock
,!**/*.lock
Files selected for processing (15)
- packages/nutui-taro-demo/package.json (2 hunks)
- scripts/rn/copy-file.js (1 hunks)
- src/config.json (2 hunks)
- src/packages/form/demo.taro.tsx (3 hunks)
- src/packages/form/demos/taro/demo1.tsx (3 hunks)
- src/packages/form/demos/taro/demo2.tsx (2 hunks)
- src/packages/form/demos/taro/demo4.tsx (2 hunks)
- src/packages/form/form.harmony.css (1 hunks)
- src/packages/form/form.scss (0 hunks)
- src/packages/form/form.taro.tsx (3 hunks)
- src/packages/form/form.tsx (1 hunks)
- src/packages/formitem/formitem.harmony.css (3 hunks)
- src/packages/formitem/formitem.scss (4 hunks)
- src/packages/formitem/formitem.taro.tsx (9 hunks)
- src/packages/formitem/formitem.tsx (7 hunks)
Files not reviewed due to no reviewable changes (1)
- src/packages/form/form.scss
Additional context used
Biome
src/packages/formitem/formitem.tsx
[error] 236-238: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
src/packages/formitem/formitem.taro.tsx
[error] 240-242: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
Additional comments not posted (71)
src/packages/form/demos/taro/demo1.tsx (2)
50-54
: 看起来不错!为
TextArea
组件添加内联样式以调整其内边距的方式是合理的。这有助于改善文本区域的视觉呈现。
Line range hint
1-60
: 请确认是否有意删除InputNumber
组件。
InputNumber
组件已从表单中完全删除。虽然这简化了表单结构,但不清楚该删除是否符合表单的要求和 PR 的目标。请验证删除
InputNumber
组件是否是有意的,并确保它与表单的整体要求保持一致。如果删除是无意的,请考虑恢复该组件。scripts/rn/copy-file.js (1)
35-35
: 看起来不错!将
'formitem'
添加到childAdaptedArray
数组中是合理的,这表明formitem
组件现在被视为一个子组件。这个改动很小,不会引入任何问题。src/packages/form/demos/taro/demo4.tsx (3)
10-10
: 看起来不错!导入
pxTransform
工具函数的语句写法正确。这个函数可能用于将像素值转换为响应式格式,有助于提高布局的适应性。
45-45
: 很好的改进!将容器的
flexDirection
样式显式设置为 'row',可以确保按钮水平对齐。这个改动增强了表单组件的布局一致性。
52-52
: 非常棒的优化!将重置按钮的
marginLeft
样式中硬编码的 '20px' 像素值替换为由pxTransform(20)
生成的动态值,使布局更具响应性。这个改动提高了表单组件在不同屏幕尺寸下的适应性。src/packages/form/demo.taro.tsx (6)
3-3
: 导入正确从
@tarojs/components
导入Text
组件是正确且必要的,以便在文件后面使用Text
组件。
13-13
: 导入正确从
@/utils/platform-taro
导入harmonyAndRn
工具函数是正确且必要的,以便在文件后面根据平台有条件地渲染某些组件。
41-43
: 改进文本处理将翻译后的文本用
Text
组件包裹可以改进文本处理,是一个很好的实践。类名 "h2" 适合用于标题。
47-52
: 根据平台有条件地渲染通过
harmonyAndRn
函数判断当前环境是否为 Harmony 或 React Native,有条件地渲染Demo3
组件,可以确保Demo3
组件只在适当的环境中显示。这增强了组件对不同平台的适应性。
55-60
: 根据平台有条件地渲染与前面的代码段类似,通过
harmonyAndRn
函数判断当前环境是否为 Harmony 或 React Native,有条件地渲染Demo5
组件,可以确保Demo5
组件只在适当的环境中显示。这增强了组件对不同平台的适应性。
64-69
: 根据平台有条件地渲染与前面的代码段类似,通过
harmonyAndRn
函数判断当前环境是否为 Harmony 或 React Native,有条件地渲染Demo7
组件,可以确保Demo7
组件只在适当的环境中显示。这增强了组件对不同平台的适应性。src/packages/form/demos/taro/demo2.tsx (3)
3-3
: 修改合理将
<div>
元素替换为 Taro 框架中的<View>
组件是合适的,因为在 Taro 中,<View>
是推荐用于布局的组件。
10-10
: 引入工具函数从
@/utils/px-transform
导入pxTransform
工具函数的语句写法正确。pxTransform
函数可能用于将像素转换为响应式单位,这是响应式设计的良好实践。
43-57
: 优化表单页脚的布局和样式这部分的修改优化了表单页脚的布局和样式:
- 将
<div>
元素替换为 Taro 框架中的<View>
组件,更适合 Taro 的渲染上下文。- 在页脚中添加了
flexDirection: 'row'
样式,确保按钮水平排列。- 使用
pxTransform
工具函数调整重置按钮的marginLeft
样式,以实现一致的像素到 rpx 的转换,提高了不同屏幕尺寸下的响应性。这些修改改善了组件的视觉结构和可维护性,而没有改变其核心功能。
src/packages/form/form.tsx (1)
99-101
: 代码修改没有问题!将
labelPosition
添加到Context.Provider
的 value 中,可以让子组件通过 context 访问到标签的位置信息。这增强了Form
组件的灵活性,使子组件能够根据标签位置来调整渲染或行为。src/packages/form/form.taro.tsx (5)
2-2
: 使用 Taro 特定的Form
组件从
@tarojs/components
导入Form
组件并将其重命名为TForm
,以使用 Taro 特定的Form
组件而不是标准的 HTML<form>
元素。这一改变增强了与 Taro 框架的兼容性,有助于构建跨平台应用。
81-81
: 使用 Taro 特定的<TForm>
组件将标准的 HTML
<form>
元素替换为 Taro 特定的<TForm>
组件,这与第 2 行的导入更改一致。使用 Taro 特定的<TForm>
组件可以增强与 Taro 框架的兼容性。
100-100
: 为Context.Provider
提供额外的上下文修改提供给
Context.Provider
的上下文,以包含formInstance
和labelPosition
。这一改变允许使用该上下文的子组件访问表单实例和标签位置。提供额外的上下文可以根据表单内标签的位置实现更动态的行为或样式。
101-102
: 使用更新后的Context.Provider
包装children
属性将
children
属性用更新后的Context.Provider
包装起来。这一改变是为了向子组件提供更新后的上下文。包装children
属性可以确保任何子组件都能从上下文中访问到formInstance
和labelPosition
。
107-107
: 关闭<TForm>
组件关闭
<TForm>
组件以匹配第 81 行的开始标签。关闭<TForm>
组件可以确保 JSX 的正确语法和结构。src/packages/formitem/formitem.scss (11)
5-11
: 代码没问题!使用 flexbox 来控制表单项标签的布局是正确的做法。代码修改看起来没有问题。
16-19
: 新增的必填标签样式 LGTM!
.nut-form-item-label-required
类正确设置了必填标签的颜色和右边距。代码修改没有问题。
20-23
: 请说明.nut-form-item-labeltxt
类的用途新增的
.nut-form-item-labeltxt
类设置了非常小的字体大小(12px)和高度(10px),可能会影响可读性。请说明一下这个类的具体用途,以及为什么要设置这么小的尺寸。
26-27
: 代码没问题!使用 flexbox 并将 flex-direction 设置为 column,可以正确控制表单项主体的纵向布局。代码修改看起来没有问题。
53-53
: 为什么要移除 textarea 的 padding?将
.nut-textarea
的 padding 设置为 0 可能会影响其视觉效果和可用性。请说明一下移除 padding 的具体原因。
102-109
: 新增的右对齐标签样式 LGTM!
.nut-form-item-label-right
类正确使用了 flexbox 的 justify-content 属性和 padding-right 将标签靠右对齐。代码修改没有问题。
111-115
: 新增的左对齐标签样式 LGTM!
.nut-form-item-label-left
类正确使用了 relative 定位和 padding-left 将标签靠左对齐。代码修改没有问题。
117-122
: 新增的左对齐必填标记样式 LGTM!
.nut-form-item-label-left-required
类正确使用了 absolute 定位将必填标记定位在左对齐标签的左侧。代码修改没有问题。
124-128
: 新增的垂直布局样式 LGTM!
.nut-form-item-top
类正确使用了 flexbox 的 flex-direction 和 align-items 属性将标签和主体垂直堆叠。代码修改没有问题。
130-134
: 新增的顶部对齐标签样式 LGTM!
.nut-form-item-label-top
类正确设置了 display、padding-bottom 和 padding-right 属性来样式化顶部对齐的标签。代码修改没有问题。
136-139
: 新增的顶部对齐主体样式 LGTM!
.nut-form-item-body-top
类正确重置了 margin-left 为 0 并将 width 设置为 100%,以适应顶部对齐的表单项主体。代码修改没有问题。src/packages/formitem/formitem.harmony.css (14)
5-6
: 代码看起来不错!使用 flexbox 布局和 row 方向可以改善标签的布局行为。
11-11
: 代码看起来不错!将 flex 属性设置为
0 0 auto
,可以防止标签增大或缩小,同时允许它采用其固有宽度。这改善了标签的布局行为。
13-13
: 代码看起来不错!将文本对齐方式设置为左对齐,可以提高多方向布局的一致性。
15-18
: 代码看起来不错!为必填标签引入专门的样式类,可以简化结构并增强可读性。
19-22
: 代码看起来不错!为标签文本设置字体大小和高度,可以改善标签文本的视觉层次结构和对齐方式。
25-27
: 代码看起来不错!使用 flexbox 布局和 column 方向可以改善表单项主体的布局行为。
29-29
: 代码看起来不错!将表单项主体插槽的文本对齐方式设置为左对齐,可以提高多方向布局的一致性。
37-38
: 代码看起来不错!将输入文本的对齐方式设置为左对齐,并设置颜色,可以提高多方向布局的一致性和视觉层次结构。
49-49
: 代码看起来不错!为文本区域删除内边距,可以改善表单项主体插槽内文本区域的布局一致性。
53-53
: 代码看起来不错!将文本区域的文本对齐方式设置为左对齐,可以提高多方向布局的一致性。
56-58
: 代码看起来不错!将表单项主体提示的文本对齐方式设置为左对齐,并设置颜色,可以提高多方向布局的一致性和错误状态的视觉层次结构。
62-65
: 代码看起来不错!为从右到左 (RTL) 布局中的表单项标签调整文本对齐方式和边距,可以确保标签在 RTL 上下文中正确对齐。
68-71
: 代码看起来不错!使用
.nut-rtl
类为从右到左 (RTL) 布局中的表单项标签调整文本对齐方式和边距,可以确保标签在 RTL 上下文中正确对齐。
80-168
: 代码看起来不错!引入新的布局类来支持不同的标签放置方式和 RTL 布局,可以增强表单项组件对各种布局要求的灵活性和适应性。
packages/nutui-taro-demo/package.json (2)
78-78
: 依赖添加没有问题!添加
async-validator
依赖是一个有效的改动,版本指定也允许在主版本号 4 的基础上进行次版本号和修订号的更新,没有引入任何问题。
115-115
: 格式更新,没有功能影响。
sass
依赖解析的改动只是格式上的调整,并没有修改版本号,因此不会产生任何功能上的影响。src/packages/form/form.harmony.css (4)
1-27
: 代码看起来不错!新增的
.nut-cell-group
、.nut-cell-group-title
、.nut-cell-group-description
和.nut-cell-group-wrap
类的样式定义合理,为单元格组元素提供了一致的样式。
57-143
: 单元格组件的样式定义全面且合理。新增的
.nut-cell
、.nut-cell-group-item
、.nut-cell-left
、.nut-cell-title
、.nut-cell-description
、.nut-cell-extra
、.nut-cell-clickable
和.nut-cell-divider
类的样式定义全面,确保了单元格组件的一致性和视觉吸引力。样式结构良好,涵盖了单元格组件的各个方面。
145-245
: 表单项组件的样式定义结构良好且全面。新增的
.nut-form-item
、.nut-form-item-label
、.nut-form-item-label-required
、.nut-form-item-body
、.nut-form-item-body-slots
和.nut-form-item-body-tips
类的样式定义结构清晰,为表单项组件提供了全面的样式。这些样式确保了表单项在不同方向(LTR 和 RTL)下的一致布局和外观。
Line range hint
248-314
: 表单项标签定位的样式定义灵活且全面。新增的
.nut-form-item-label-right
、.nut-form-item-label-left
、.nut-form-item-label-left-required
、.nut-form-item-top
、.nut-form-item-label-top
和.nut-form-item-body-top
类的样式定义提供了灵活且全面的表单项标签定位方式。这些样式涵盖了各种标签位置(右、左和顶部),并确保了正确的对齐和间距。每个位置的 RTL 支持也得到了正确处理。src/packages/formitem/formitem.tsx (11)
60-60
: 变更看起来不错!使用明确赋值断言表明
context
会在使用前被赋值,这在语法上是正确的。请确保在使用context
之前,它确实已经被赋值,以避免运行时错误。
78-79
: 看起来很棒!从
this.context.formInstance.getInternal(SECRET)
中解构store
和setInitialValues
属性,与更新后的上下文结构保持一致。为store
设置默认值{}
是一个很好的做法,可以处理store
可能为 undefined 的情况。
91-92
: 变更看起来不错!从
this.context.formInstance.getInternal(SECRET)
中获取registerField
和registerUpdate
方法,与更新后的上下文结构保持一致。这个变更没有引入任何新逻辑或改变现有行为。
109-110
: 看起来很棒!直接从
this.context.formInstance
获取setFieldsValue
和getFieldValue
方法,同时从this.context.formInstance.getInternal(SECRET)
获取dispatch
方法,与更新后的上下文结构保持一致。将setFieldsValue
和getFieldValue
直接从this.context.formInstance
访问,似乎是一个有意的改变,可能是因为这些方法现在直接在formInstance
上公开。
184-184
: 变更看起来不错!直接从
this.context.formInstance
访问errors
属性,与更新后的上下文结构保持一致。将errors
直接从this.context.formInstance
访问,似乎是一个有意的改变,可能是因为这个属性现在直接在formInstance
上公开。
191-196
: 新增的方法看起来很棒!
getClassNameWithDirection
方法根据表单上下文中配置的labelPosition
,生成相应的类名。它通过考虑标签位置来增强组件的样式功能。这个方法的逻辑很简单,不会引入任何潜在问题。
214-214
: 看起来很棒!直接从
this.context.formInstance
访问errors
属性,与更新后的上下文结构保持一致。将errors
直接从this.context.formInstance
访问,似乎是一个有意的改变,可能是因为这个属性现在直接在formInstance
上公开。
216-218
: 变更看起来不错!直接从
this.context.formInstance
访问starPosition
属性,与更新后的上下文结构保持一致。将starPosition
直接从this.context.formInstance
访问,似乎是一个有意的改变,可能是因为这个属性现在直接在formInstance
上公开。根据required
属性或是否存在required
规则来渲染星号元素的逻辑很简单,不会引入任何潜在问题。
223-223
: 看起来很棒!这个变更渲染了一个具有
nut-form-item-labeltxt
类的 span 元素,并将label
属性作为其内容。它没有引入任何新逻辑或改变现有行为,只是对渲染的标签元素进行了小幅更新。
229-245
: 变更看起来不错!这个变更利用新引入的
getClassNameWithDirection
方法,根据labelPosition
生成nut-form-item
、nut-form-item-label
和nut-form-item-body
元素的类名。它通过考虑标签位置来增强组件的样式功能。getClassNameWithDirection
在相关元素中的使用是一致的。Tools
Biome
[error] 236-238: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
270-270
: 看起来很棒!这个变更将
this.context.formInstance
作为参数调用children
函数,与更新后的上下文结构保持一致。将this.context.formInstance
传递给children
函数,允许子组件直接访问表单实例。src/packages/formitem/formitem.taro.tsx (6)
59-59
: 修改看起来不错!将
contextType
静态属性更新为直接使用Context
,提高了类型安全性。
80-81
: 很好的重构!将上下文访问更新为使用
formInstance
,封装了内部方法和属性。这提高了可维护性,减少了与上下文结构的直接耦合。变更是一致的,没有引入任何问题。
Also applies to: 93-94
111-112
: 很好的改进!对
getControlled
和onStoreChange
方法的更改与使用formInstance
的更新上下文访问模式一致。新的
getClassNameWithDirection
方法根据上下文中的labelPosition
调整布局,提高了组件的灵活性。这些更改增强了组件与表单上下文的集成,没有引入任何问题。
Also applies to: 122-122, 188-188, 195-200
218-218
: 渲染逻辑的改进很好!使用
getClassNameWithDirection
方法根据上下文动态调整类名,提高了组件布局的适应性。引入
Text
组件增强了必填指示器的语义结构。对
renderLayout
方法的重构是合理的,没有引入任何问题。Also applies to: 220-222, 227-227, 233-233, 241-243, 247-249
276-276
: 条件渲染看起来不错。基于
shouldUpdate
属性的条件渲染似乎是合理的,没有引起任何问题。
240-242
: 可以跳过静态分析提示。当前的代码检查
label
是否为真值,然后有条件地渲染标签内容。这是安全的,不需要可选链。在这种情况下,静态分析提示是一个误报。
Tools
Biome
[error] 240-242: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
src/config.json (2)
495-495
: 重大版本更新:请验证文档和用法是否已更新。"Form"组件的版本已从"2.0.0"更改为"3.0.0",这表示该组件进行了重大更新。
请确保:
- "Form"组件的文档已更新,以反映新版本中的更改。
- 代码库中"Form"组件的用法已更新,以匹配新版本。
506-506
: 重大版本更新:请验证文档和用法是否已更新。"FormItem"组件的版本已从"2.0.0"更改为"3.0.0",这表示该组件进行了重大更新。
请确保:
- "FormItem"组件的文档已更新,以反映新版本中的更改。
- 代码库中"FormItem"组件的用法已更新,以匹配新版本。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Outside diff range and nitpick comments (9)
scripts/rn/copy-file.js (3)
Line range hint
1-91
: 建议增强脚本的健壮性和可维护性当前脚本在处理组件适配时有以下几点可以改进:
- 版本号硬编码('3.0.0')可能导致维护困难
- 文件操作缺少适当的错误恢复机制
- 缺少对文件路径有效性的检查
建议进行以下优化:
const config = require('../../src/config.json') +const SUPPORTED_VERSION = '3.0.0' + +const validatePaths = (paths) => { + return paths.every(p => fse.existsSync(p)) +} + +const handleError = (err, operation) => { + console.error(`Error during ${operation}:`, err) + process.exit(1) +} // 已适配组件对象 const adaptedArray = [] config.nav.map((item) => { item.packages.forEach((element) => { const { name, version } = element - if (version !== '3.0.0') return // 未适配不导出 + if (version !== SUPPORTED_VERSION) return // 未适配不导出 adaptedArray.push({ ...element, lowercaseName: element.name.toLowerCase(), enName: item.enName, }) }) }) const copyFile = async (from, to, success, isSingle = false) => { + if (!validatePaths([from])) { + handleError(new Error(`Source path ${from} does not exist`), 'validation') + return + } fse.copy(from, to, function (err) { if (err) { - console.error('An error occurred while copying the directory.', err) - return + handleError(err, 'copy') + return } // ... rest of the function }) }
Line range hint
1-91
: 建议添加配置文件验证为了确保配置文件的正确性,建议添加配置验证机制。
建议添加以下验证逻辑:
+const validateConfig = (config) => { + if (!config.nav || !Array.isArray(config.nav)) { + throw new Error('配置文件格式错误:缺少 nav 数组') + } + + config.nav.forEach((item, index) => { + if (!item.packages || !Array.isArray(item.packages)) { + throw new Error(`配置文件格式错误:nav[${index}] 缺少 packages 数组`) + } + }) +} const config = require('../../src/config.json') +validateConfig(config)
Line range hint
1-91
: 建议优化日志输出当前的日志输出不够结构化,建议改进日志格式以便于调试和监控。
建议添加以下日志工具:
+const logger = { + info: (msg, data) => console.log(`[INFO] ${msg}`, data || ''), + error: (msg, err) => console.error(`[ERROR] ${msg}`, err || ''), + success: (msg, data) => console.log(`[SUCCESS] ${msg}`, data || '') +} const copyFile = async (from, to, success, isSingle = false) => { fse.copy(from, to, function (err) { if (err) { - console.error('An error occurred while copying the directory.', err) + logger.error('复制目录失败', err) return } - console.log(`${success}!>`, to) + logger.success(success, to) // ... rest of the function }) }src/packages/formitem/formitem.taro.tsx (5)
Line range hint
80-94
: 组件注册逻辑优化建议建议将注册相关的逻辑抽取到单独的方法中,提高代码可维护性。同时,建议添加错误处理机制。
+ private registerFormField() { + try { + const { store = {}, setInitialValues, registerField, registerUpdate } = + this.context.formInstance.getInternal(SECRET) + + if ( + this.props.initialValue && + this.props.name && + !Object.keys(store).includes(this.props.name) + ) { + setInitialValues( + { ...store, [this.props.name]: this.props.initialValue }, + true + ) + } + + this.cancelRegister = registerField(this) + this.eventOff = registerUpdate(this, this.props.shouldUpdate) + } catch (error) { + console.error('表单字段注册失败:', error) + } + }
111-112
: 简化上下文访问建议使用解构赋值简化代码,提高可读性。
- const { setFieldsValue, getFieldValue } = this.context.formInstance - const { dispatch } = this.context.formInstance.getInternal(SECRET) + const { formInstance } = this.context + const { setFieldsValue, getFieldValue } = formInstance + const { dispatch } = formInstance.getInternal(SECRET)
195-200
: 方向类名处理优化建议添加空值检查并使用模板字符串简化代码。
getClassNameWithDirection(className: string) { - if (className && this.context.labelPosition) { - return `${className} ${className}-${this.context.labelPosition}` - } - return className + const { labelPosition } = this.context + return className && labelPosition + ? `${className} ${className}-${labelPosition}` + : className }
241-243
: 优化条件渲染建议使用可选链操作符来简化代码。
- <View - className={`nut-cell-title ${this.getClassNameWithDirection('nut-form-item-label')}`} - > + <View + className={`nut-cell-title ${this.getClassNameWithDirection?.('nut-form-item-label') ?? ''}`} + >
247-249
: 表单项样式适配建议考虑到多端适配的需求,建议为不同平台添加特定的样式类名。
建议添加平台特定的类名,例如:
getClassNameWithPlatform(className: string) { const platform = process.env.TARO_ENV return `${className} ${className}-${platform}` }然后在样式中处理不同平台的特殊情况:
.nut-form-item-body-rn { /* RN 特定样式 */ } .nut-form-item-body-harmony { /* HarmonyOS 特定样式 */ }src/config.json (1)
Line range hint
518-565
: 新增表单相关组件完善了多端适配方案新增的 Input、InputNumber、Range、Switch、TextArea 等组件都采用 3.0.0 版本,这些组件的添加完善了表单系统,使其更好地支持多平台场景。建议:
- 确保这些新组件在 React Native 和 HarmonyOS 上都经过充分测试
- 考虑为这些组件添加平台特定的样式降级方案
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (4)
scripts/rn/copy-file.js
(1 hunks)src/config.json
(2 hunks)src/packages/form/demos/taro/demo1.tsx
(3 hunks)src/packages/formitem/formitem.taro.tsx
(9 hunks)
🧰 Additional context used
🪛 Biome
src/packages/formitem/formitem.taro.tsx
[error] 240-242: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
🔇 Additional comments (4)
src/packages/form/demos/taro/demo1.tsx (2)
2-2
: 导入语句的清理看起来不错!
移除未使用的 InputNumber
组件导入,使代码更加简洁。
50-54
: 请验证 TextArea 在多端的样式表现
虽然添加了 paddingTop
和 paddingBottom
的样式调整,但建议:
- 确认这些样式在 React Native 和 HarmonyOS 上是否正常工作
- 验证是否需要添加其他样式属性来确保跨平台的一致性
运行以下脚本来检查是否有其他相关的样式适配:
scripts/rn/copy-file.js (1)
35-35
: 新增 formitem 子组件适配支持
'formitem' 的添加符合多端适配的需求,确保表单项组件能够正确处理样式文件。
src/config.json (1)
Line range hint 495-517
: 版本升级变更符合多端适配需求
Form 和 FormItem 组件从 2.0.0 升级到 3.0.0 的变更与 PR 的多端适配目标相符,这将有助于解决 React Native 和 HarmonyOS 中的样式选择器限制问题。
✅ Verification successful
Form组件版本升级变更已确认安全
根据代码库搜索结果,Form组件升级到3.0.0版本是独立且完整的变更,没有发现其他配置文件引用旧版本,也未发现潜在的版本冲突。此次版本升级符合多端适配的需求。
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# 检查是否有其他配置文件引用了旧版本的 Form 组件
rg -l "\"version\":\s*\"2\.0\.0\".*\"Form\""
Length of output: 40
Script:
#!/bin/bash
# 使用更宽松的搜索模式查找所有 Form 相关的配置
rg -i "form.*version" --type json
# 检查其他可能包含版本信息的配置文件
fd -e json -x cat {} | grep -i "form"
# 查找可能的组件引用
rg -i "form.*component" --type json
Length of output: 2515
Script:
#!/bin/bash
# 查找所有包含 Form 组件配置的文件
rg -A 5 -B 5 '"name":\s*"Form"' --type json
# 检查组件版本历史
git log -p -- src/config.json | grep -A 10 -B 10 '"version".*"Form"'
# 查找相关的组件引用关系
rg -A 3 "import.*Form" --type ts --type tsx --type jsx
Length of output: 570
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## V3.0 #2595 +/- ##
=======================================
Coverage 83.95% 83.95%
=======================================
Files 221 221
Lines 17849 17849
Branches 2679 2679
=======================================
Hits 14986 14986
Misses 2858 2858
Partials 5 5 ☔ View full report in Codecov by Sentry. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
🧹 Outside diff range and nitpick comments (16)
src/utils/merge.ts (3)
8-10
: 数组合并策略需要重新考虑。当前实现直接覆盖数组,这可能不是所有场景下的最佳选择。建议考虑提供数组合并策略选项。
建议添加合并策略参数:
+interface MergeOptions { + arrayMergeStrategy?: 'replace' | 'concat' | 'unique'; +} + -export function merge<T extends object>(...objects: (T | null | undefined)[]): T { +export function merge<T extends object>( + options: MergeOptions = {}, + ...objects: (T | null | undefined)[] +): T { // ... if (Array.isArray(value)) { - result[key] = [...value] + switch (options.arrayMergeStrategy) { + case 'concat': + result[key] = result[key] ? [...result[key], ...value] : [...value]; + break; + case 'unique': + result[key] = result[key] + ? [...new Set([...result[key], ...value])] + : [...value]; + break; + default: + result[key] = [...value]; + } }
26-28
: 建议添加性能优化。对于大量对象的合并操作,当前实现可能存在性能问题。建议添加缓存机制并优化过滤逻辑。
建议修改如下:
- objects.filter((obj) => !!obj).forEach((obj) => mergeHelper(obj)) + const validObjects = objects.filter(Boolean) + if (validObjects.length === 0) return result + if (validObjects.length === 1) return { ...validObjects[0] } + + validObjects.forEach((obj) => mergeHelper(obj))
1-29
: 请添加单元测试覆盖边界情况。建议添加完整的单元测试,覆盖以下场景:
- 空对象合并
- 数组合并
- 循环引用
- 深层嵌套对象
- 不同类型值的合并
需要我帮您生成相应的单元测试代码吗?
src/packages/form/form.tsx (1)
102-104
: Context 数据结构调整建议将 formInstance、labelPosition 和 disabled 组合成对象传递给 Context.Provider 是个好的改进,但建议考虑以下几点:
- 考虑添加 TypeScript 类型定义来约束 Context 值的结构
- 建议在组件内部添加相关文档注释,说明 Context 值的用途
+// 定义 Context 值的类型 +interface FormContextValue { + formInstance: FormInstance; + labelPosition: 'top' | 'left' | 'right'; + disabled: boolean; +} +// Form 组件的 Context,用于向子组件传递表单状态 <Context.Provider value={{ formInstance, labelPosition, disabled }}> {children} </Context.Provider>src/packages/form/form.taro.tsx (2)
Line range hint
84-99
: 建议优化事件处理逻辑当前的事件处理实现是正确的,但可以进行小幅优化以提高代码可维护性。
建议将事件处理函数提取为独立的方法:
+ const handleSubmit = (e) => { + e.preventDefault() + e.stopPropagation() + submit() + } + + const handleReset = (e) => { + e.preventDefault() + e.stopPropagation() + resetFields() + } + return ( <TForm className={classNames(classPrefix, PositionInfo[labelPosition], className)} style={style} - onSubmit={(e) => { - e.preventDefault() - e.stopPropagation() - submit() - }} - onReset={(e) => { - e.preventDefault() - e.stopPropagation() - resetFields() - }} + onSubmit={handleSubmit} + onReset={handleReset} >
Line range hint
1-112
: 建议考虑更明确的多端适配策略当前的实现通过使用 Taro 组件实现了多端适配,这是一个好的开始。不过,建议考虑以下几点来增强多端适配的可维护性:
- 考虑添加平台特定的样式文件,便于处理不同平台的样式差异
- 可以考虑使用 HOC 或自定义 hooks 来封装平台特定的逻辑
- 建议添加平台特定的单元测试用例
这些改进可以让多端适配的代码更容易维护和扩展。
src/packages/formitem/formitem.scss (3)
Line range hint
31-58
: 建议优化输入框在不同平台的样式兼容性当前实现存在以下可优化点:
- 移除内边距可能导致在某些平台上触摸区域过小
- 文本域样式可能需要针对 RN 和 HarmonyOS 做特殊处理
建议添加以下平台特定样式:
.nut-textarea { .nut-textarea-textarea { #ifdef RN padding: 8px; min-height: 24px; #endif #ifdef HARMONY padding: 6px; min-height: 20px; #endif } }
Line range hint
73-106
: 建议补充 RTL 支持的使用说明RTL 支持的实现非常完整,建议:
- 在组件文档中添加 RTL 支持的使用说明
- 补充示例代码展示如何在不同平台启用 RTL
建议在组件文档中添加如下说明:
## RTL 支持 FormItem 组件支持 RTL(从右到左)布局: - React Native:通过设置 `dir="rtl"` 启用 - HarmonyOS:通过 CSS 类 `.nut-rtl` 启用
110-175
: 建议优化位置相关样式的代码组织当前实现功能完整,但代码组织可以更清晰:
- 建议将位置相关样式按功能分组:
- 标准布局样式
- RTL 适配样式
- 响应式布局样式
建议重构为以下结构:
// 布局基础样式 .nut-form-item { &-label { &-right { ... } &-left { ... } &-top { ... } } } // RTL 适配 [dir='rtl'], .nut-rtl { .form-layout { &-right { ... } &-left { ... } &-top { ... } } }src/packages/form/useform.taro.ts (2)
88-93
: 优化 setInitialValues 方法但需要移除调试代码使用 merge 函数来处理初始值的更新是个很好的改进,但是需要移除第 93 行的 console.log 语句。
建议应用以下修改:
setInitialValues = (initialValues: Store, init: boolean) => { this.initialValues = initialValues || {} if (init) { const nextStore = merge(initialValues, this.store) this.updateStore(nextStore) - console.log(this.store === this.initialValues) } }
193-195
: 优化 resetFields 但需要移除调试代码使用 merge 来创建初始值的副本是个好做法,但需要移除第 194 行的 console.log 语句。
建议应用以下修改:
const nextStore = merge({}, this.initialValues) - console.log('xxx', nextStore, this.initialValues) this.updateStore(nextStore)
src/packages/form/useform.ts (3)
3-3
: 优化:Store 管理逻辑改进代码重构提升了可维护性:
- 引入 merge 工具函数确保了数据不可变性
- 新增 updateStore 方法统一了状态更新逻辑
- setInitialValues 和 setFieldsValue 方法现在通过 merge 来更新状态
建议进一步改进:
updateStore(nextStore: Store) { + // 添加状态变更的订阅机制,便于后续扩展(如:状态追踪、性能分析等) this.store = nextStore }
Also applies to: 78-80, 88-92, 100-102
192-193
: 建议:重置逻辑可以优化当前实现存在以下可以改进的地方:
- errors 的重置使用 length = 0 不够优雅
- 缺少重置状态的事件通知机制
resetFields = () => { - this.errors.length = 0 + this.errors = {} const nextStore = merge({}, this.initialValues) this.updateStore(nextStore) + // 触发重置事件,便于上层组件感知状态变化 + this.callbacks.onReset?.(nextStore) this.fieldEntities.forEach((entity: FormFieldEntity) => { entity.onStoreChange('reset') }) }
7-7
: 建议:类型定义可以更严格虽然添加了 FormInstance 类型,但还可以进一步改进类型安全性:
- return [formRef.current as FormInstance] + return [formRef.current!] // 使用非空断言,因为我们确定这里一定有值建议:
- 考虑为 Store 类型添加泛型支持
- 为回调函数添加更具体的类型定义
Also applies to: 9-9, 251-251
src/packages/formitem/formitem.taro.tsx (2)
61-61
: 建议改进类型安全性虽然使用
!
操作符可以解决类型检查问题,但建议通过以下方式提供更好的类型安全性:
- 在构造函数中验证 context
- 使用可选链操作符来安全访问 context
- context!: React.ContextType<typeof Context> + context: React.ContextType<typeof Context> constructor(props: FormItemProps) { super(props) + if (!this.context?.formInstance) { + throw new Error('FormItem must be used within Form') + } this.componentRef = React.createRef() this.state = { resetCount: 1, } }Also applies to: 79-80
194-199
: 建议增强无障碍性支持当前的多端适配改动很好,建议进一步增强无障碍性支持:
- 为表单项添加 ARIA 属性
- 确保错误消息能被屏幕阅读器正确读取
- 在禁用状态下提供视觉反馈
<View - className={this.context.disabled ? 'nut-form-item-disabled' : ''} + className={this.context.disabled ? 'nut-form-item-disabled' : ''} + aria-disabled={this.context.disabled} + role="group" + aria-label={this.props.label} catchMove={this.context.disabled} >Also applies to: 279-286
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (8)
src/packages/form/form.taro.tsx
(6 hunks)src/packages/form/form.tsx
(4 hunks)src/packages/form/useform.taro.ts
(5 hunks)src/packages/form/useform.ts
(5 hunks)src/packages/formitem/formitem.scss
(4 hunks)src/packages/formitem/formitem.taro.tsx
(10 hunks)src/packages/formitem/formitem.tsx
(9 hunks)src/utils/merge.ts
(1 hunks)
🧰 Additional context used
🪛 Biome
src/packages/formitem/formitem.taro.tsx
[error] 239-241: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
src/packages/formitem/formitem.tsx
[error] 238-240: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
🔇 Additional comments (28)
src/packages/form/form.tsx (3)
14-14
: 新增 disabled 属性类型定义
在 FormProps 接口中添加 disabled 布尔类型属性,用于控制表单的禁用状态,符合多端适配的需求。
26-26
: 默认值设置合理
为 disabled 属性设置默认值为 false 是符合预期的,这样默认情况下表单是可交互的。
48-48
: Props 解构完整性验证
从 props 中解构出 disabled 属性,建议验证一下在各端(RN、HarmonyOS)的兼容性。
✅ Verification successful
disabled
属性在各端已正确实现
根据代码分析,disabled
属性已在以下文件中得到一致的实现:
src/packages/form/form.tsx
(Web端)src/packages/form/form.taro.tsx
(小程序端)
两个平台的实现完全一致,包括:
- 在 Props 类型定义中声明
disabled: boolean
- 默认值设置为
disabled: false
- 通过 Context.Provider 传递给子组件
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# 检查其他平台特定文件中是否也正确处理了 disabled 属性
rg -l "disabled.*FormProps" src/packages/form/
Length of output: 48
Script:
#!/bin/bash
# 搜索 form.tsx 相关文件
fd "form\.(tsx|ts)" src/packages/form/
# 搜索所有包含 disabled 属性的相关代码
rg "disabled" src/packages/form/ -A 2 -B 2
Length of output: 2324
src/packages/form/form.taro.tsx (2)
2-2
: 导入和属性变更看起来不错!
引入 Taro 的 Form 组件替代原生 form 元素是正确的选择,这样可以更好地支持多端适配。disabled
属性的添加也很合理,包括了适当的类型定义和默认值设置。
Also applies to: 15-15, 27-27
103-105
: 验证子组件的 Context 使用情况
Context 中添加了 disabled
状态,这个改动是合理的。但需要确保所有消费这个 Context 的子组件都正确处理了这个新增的状态。
运行以下脚本来验证相关组件的实现:
✅ Verification successful
Context 中的 disabled 状态已正确处理
FormItem 组件已经正确处理了 Form Context 中的 disabled 状态:
- 在 disabled 为 true 时添加了
nut-form-item-disabled
类名 - 设置了相应的样式(opacity: 0.4 和 pointerEvents: none)
- 在 Taro 版本中还添加了
catchMove
属性以禁用事件
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# 搜索所有使用 Form Context 的组件
rg -l "useContext.*Context.*form" src/packages/
Length of output: 49
Script:
#!/bin/bash
# 使用更广泛的搜索模式来查找 Context 的使用
rg -l "useContext.*Context" src/packages/
# 搜索可能的 Context 导入
rg "import.*Context.*from.*form" src/packages/
# 直接搜索 Context 的使用
rg "Context\.Consumer" src/packages/
# 使用 ast-grep 查找 useContext 的使用
ast-grep --pattern 'useContext($$$)'
Length of output: 3420
Script:
#!/bin/bash
# 检查 FormItem 组件中如何使用 Form Context
rg -A 5 "useContext\(Context\)" src/packages/formitem/
# 查看 Form Context 的定义
cat src/packages/form/context.ts
# 检查其他可能使用 Form Context 的文件
rg "from.*['\"]\.\.\/form\/" src/packages/
Length of output: 345
Script:
#!/bin/bash
# 修正搜索语法,检查引用 form 相关文件的组件
rg "from.*\.\./form/" src/packages/
# 检查 FormItem 组件的实现
cat src/packages/formitem/formitem.tsx
cat src/packages/formitem/formitem.taro.tsx
Length of output: 16104
src/packages/formitem/formitem.scss (1)
4-28
: 表单项基础样式实现合理!
禁用状态和标签样式的实现符合最佳实践:
- 禁用状态使用 opacity 和 pointer-events 的组合是标准做法
- 标签布局采用 flex 布局提高了灵活性
- 必填标记的样式清晰醒目
src/packages/form/useform.taro.ts (4)
3-3
: 引入 merge 工具函数并添加统一的 store 更新方法
引入 merge 工具函数并添加 updateStore 方法是一个很好的改进,它提供了一个统一的更新 store 的入口点,增强了代码的可维护性。
Also applies to: 78-80
101-103
: 改进 setFieldsValue 的实现
使用 merge 和 updateStore 的组合优化了状态更新逻辑,使代码更加清晰和可维护。
149-149
: 简化错误处理逻辑
validateEntities 方法中的错误处理逻辑变得更加简洁,直接解构 errors 对象是个很好的改进。
253-253
: 增强类型安全性
在 useForm 的返回值中添加类型断言提高了类型安全性,这是一个很好的改进。
src/packages/formitem/formitem.taro.tsx (1)
92-93
: 注册逻辑完善
表单字段注册和清理的实现很规范,包括:
- 正确使用 formInstance 注册字段
- 适当的清理机制
src/packages/formitem/formitem.tsx (17)
1-1
: 新增 CSSProperties
的导入
第 1 行,添加了对 CSSProperties
的导入,以支持后续代码中对样式属性的类型声明,这是合理的修改。
60-60
: 使用非空断言 !
声明 context
属性
在第 60 行,将 context
属性声明为非空断言:context!: React.ContextType<typeof Context>
。请确保组件在生命周期中正确赋值 context
,以避免潜在的运行时错误。
78-79
: 更新对 formInstance
的访问方式
在第 78-79 行,修改了对 this.context
的访问方式,改为 this.context.formInstance.getInternal(SECRET)
。请确认 formInstance
在 context
中已正确初始化,以确保方法调用的可靠性。
91-92
: 更新注册方法的调用
在第 91-92 行,使用 this.context.formInstance.getInternal(SECRET)
获取 registerField
和 registerUpdate
方法。请确保这些方法在 formInstance
中已正确定义。
109-110
: 获取字段值和分发器时更新了对 formInstance
的引用
在第 109-110 行,直接从 this.context.formInstance
中获取 setFieldsValue
、getFieldValue
和 dispatch
。这提高了代码的清晰度和可读性。
135-135
: 简化 setFieldsValue
方法的调用
在第 135 行,调用 setFieldsValue
时移除了第二个参数,简化了方法调用。这使代码更加简洁。
186-186
: 重置错误信息时更新了错误列表的访问
在第 186 行,修改了对错误信息的访问方式,使用 this.context.formInstance.errors
,确保错误状态的正确更新。
193-198
: 新增 getClassNameWithDirection
方法
在第 193-198 行,添加了 getClassNameWithDirection
方法,根据 labelPosition
动态生成类名,优化了样式管理,增强了代码的可维护性。
216-218
: 调整错误信息的获取方式
在第 216 行,更改了获取错误信息的方式,使用 this.context.formInstance.errors[name]
获取对应字段的错误信息。在第 218 行,直接从 this.context.formInstance
中获取 starPosition
,使代码更简洁。
220-220
: 改进必填字段星号的渲染
在第 220 行,渲染必填字段的星号时,添加了 nut-form-item-label-required
类名,便于样式定制。
225-225
: 优化标签文本的渲染结构
在第 225 行,使用 span
元素包裹标签文本,增加了 nut-form-item-labeltxt
类名,有利于样式的统一管理。
231-231
: 使用 getClassNameWithDirection
方法统一类名
在第 231 行,调用 this.getClassNameWithDirection('nut-form-item')
方法,动态生成类名,提升了代码的可读性和一致性。
239-241
: 统一标题部分的类名处理
在第 239-241 行,使用 getClassNameWithDirection
方法处理标题部分的类名,确保了组件在不同 labelPosition
下的样式一致性。
245-247
: 统一内容部分的类名处理
在第 245-247 行,使用 getClassNameWithDirection
方法处理内容部分的类名,进一步强化了样式管理的统一性。
272-272
: 调整 returnChildNode
的赋值逻辑
在第 272 行,当 shouldUpdate
为 true
时,直接调用子组件函数,传入 this.context.formInstance
。这使组件在需要更新时能够获取最新的表单实例。
274-276
: 根据禁用状态设置样式
在第 274-276 行,添加了对 this.context.disabled
的判断,设置了对应的样式属性,使组件在禁用状态下表现出视觉上的差异,提升了用户体验。
279-283
: 根据禁用状态调整渲染结构
在第 279-283 行,使用 this.context.disabled
判断,添加了对应的类名,并根据 noStyle
属性决定渲染内容。确保了组件在不同状态下的正确渲染。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Outside diff range and nitpick comments (9)
src/packages/form/types.ts (1)
26-26
: 建议完善参数类型文档将
setFieldsValue
的参数类型从any
改进为Store
接口是很好的改进。建议在代码注释中说明Store
接口的使用方式,以帮助开发者正确使用。建议添加以下注释:
+ /** + * 设置表单的值 + * @param value 一个对象,key 为字段名,value 为字段值 + */ setFieldsValue: (value: Store) => voidsrc/packages/form/doc.md (1)
127-128
: API 文档更新清晰且完整新增的说明和方法有助于开发者更好地理解和使用表单实例:
setFieldsValue
的说明更加明确,提醒开发者注意对象修改的影响- 新增的
setFieldValue
方法为单个字段值的设置提供了便利建议补充一个使用示例,以便开发者更好地理解这两个方法的区别:
// setFieldsValue 示例 form.setFieldsValue({ username: 'nutui', password: '123456' }); // setFieldValue 示例 form.setFieldValue('username', 'nutui');src/packages/form/doc.zh-TW.md (1)
128-128
: 新增的 API 使用更灵活!新增的
setFieldValue
方法很实用,可以更精确地控制单个字段的值。建议补充一个使用示例,以便用户更好地理解。建议添加示例代码:
| setFieldValue | 設定對應欄位名的值 | `<T>(name: NamePath, value: T) => void` | + +例如: +```tsx +// 设置单个字段的值 +form.setFieldValue('username', 'nutui'); + +// 设置嵌套字段的值 +form.setFieldValue(['user', 'name'], 'nutui'); +```src/packages/form/doc.taro.md (1)
127-128
: API 文档更新清晰且完整
setFieldsValue
和setFieldValue
的文档说明准确描述了这两个方法的用途和行为差异:
setFieldsValue
的补充说明有助于开发者避免对象修改带来的副作用setFieldValue
作为新增方法,其描述简洁明了建议补充一个示例代码,以便更直观地展示这两个方法的使用方式。
可以在文档中添加如下示例:
// setFieldsValue 示例 form.setFieldsValue({ username: 'nutui', password: '123456' }); // setFieldValue 示例 form.setFieldValue('username', 'nutui');src/packages/form/useform.taro.ts (3)
78-80
: 建议增强 updateStore 方法的健壮性当前实现直接更新 store,建议添加以下增强:
- 添加参数类型验证
- 考虑添加不可变性处理
- 添加更新前的防御性检查
建议修改为:
updateStore(nextStore: Store) { + if (!nextStore || typeof nextStore !== 'object') { + throw new Error('nextStore must be a valid object') + } - this.store = nextStore + this.store = { ...nextStore } }
Line range hint
100-120
: 建议优化 setFieldsValue 的性能和可维护性当前实现存在以下可优化点:
- 嵌套循环可能导致性能问题
- 更新通知逻辑较为复杂
建议重构为:
setFieldsValue = (newStore: any) => { const nextStore = merge(this.store, newStore) this.updateStore(nextStore) - this.fieldEntities.forEach((entity: FormFieldEntity) => { - const { name } = entity.props - Object.keys(newStore).forEach((key) => { - if (key === name) { - entity.onStoreChange('update') - } - }) - }) + const updatedFields = new Set(Object.keys(newStore)) + this.fieldEntities + .filter(entity => updatedFields.has(entity.props.name)) + .forEach(entity => entity.onStoreChange('update')) this.updateList.forEach((item: UpdateItem) => { let shouldUpdate = item.condition if (typeof item.condition === 'function') { shouldUpdate = item.condition() } if (shouldUpdate) { item.entity.onStoreChange('update') } }) }
199-200
: 建议增强 resetFields 的错误处理当前实现可能在 initialValues 无效时出现问题。建议添加防御性编程:
resetFields = () => { this.errors.length = 0 + if (!this.initialValues || typeof this.initialValues !== 'object') { + console.warn('Invalid initialValues detected during reset') + this.initialValues = {} + } const nextStore = merge({}, this.initialValues) this.updateStore(nextStore) this.fieldEntities.forEach((entity: FormFieldEntity) => { entity.onStoreChange('reset') }) }src/packages/form/useform.ts (2)
88-92
: 建议:初始化逻辑可以更严谨初始化逻辑需要考虑以下场景:
initialValues
为null
或undefined
的处理- 深层对象的合并策略
建议如下修改:
setInitialValues = (initialValues: Store, init: boolean) => { - this.initialValues = initialValues || {} + this.initialValues = initialValues ?? {} if (init) { const nextStore = merge(initialValues, this.store) this.updateStore(nextStore) } }
Line range hint
100-120
: 建议:优化字段更新的性能当前实现在更新字段时会遍历所有实体,这在表单项较多时可能会影响性能。
建议优化如下:
setFieldsValue = (newStore: any) => { const nextStore = merge(this.store, newStore) this.updateStore(nextStore) + const updatedFields = new Set(Object.keys(newStore)) this.fieldEntities.forEach((entity: FormFieldEntity) => { const { name } = entity.props - Object.keys(newStore).forEach((key) => { - if (key === name) { - entity.onStoreChange('update') - } - }) + if (updatedFields.has(name)) { + entity.onStoreChange('update') + } }) // ... rest of the code }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (7)
src/packages/form/doc.en-US.md
(1 hunks)src/packages/form/doc.md
(1 hunks)src/packages/form/doc.taro.md
(1 hunks)src/packages/form/doc.zh-TW.md
(1 hunks)src/packages/form/types.ts
(2 hunks)src/packages/form/useform.taro.ts
(7 hunks)src/packages/form/useform.ts
(7 hunks)
🔇 Additional comments (14)
src/packages/form/types.ts (3)
3-4
: 正确添加了正则表达式验证支持!
在 FormItemRuleWithoutValidator
接口中添加可选的 regex
属性是一个很好的改进,这样可以支持更灵活的表单验证规则。
24-24
: 类型安全的字段值设置方法!
新增的 setFieldValue
方法使用泛型参数很合理,可以保证类型安全性。这对于表单控件的精确控制很有帮助。
Line range hint 3-26
: 验证多端适配的类型兼容性
考虑到这是多端适配相关的改动,我们需要确保这些类型定义在 React Native 和 HarmonyOS 环境下都能正常工作。
✅ Verification successful
类型定义已经适配多端环境,无需额外修改
根据检查结果,当前的类型定义已经完全支持多端适配:
- 类型定义位于通用的
types.ts
文件中,被 H5(form.tsx
)和 Taro(form.taro.tsx
)等不同平台共用 - 在
useform.ts
和useform.taro.ts
中都正确引用和实现了这些类型 - 没有发现平台特定的类型定义文件,说明这些类型是跨平台通用的
- 项目中已包含了对 React Native 和 HarmonyOS 的支持配置
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# 检查是否有平台特定的类型定义文件
echo "检查平台特定的类型定义..."
fd -e ts -e tsx "types?.+(rn|harmony).ts"
# 检查是否有使用这些类型的平台特定实现
echo "检查平台特定的实现..."
rg -t ts -t tsx "FormInstance|FormItemRuleWithoutValidator" -g "**(rn|harmony)/**"
Length of output: 452
Script:
#!/bin/bash
# 修正命令,检查平台特定的类型定义文件
echo "检查平台特定的类型定义..."
fd "types" -e ts
# 修正命令,检查平台特定实现
echo "检查使用这些类型的实现..."
rg "FormInstance|FormItemRuleWithoutValidator" -t ts
# 检查是否存在平台特定的目录
echo "检查平台特定目录..."
fd -t d "(rn|harmony)"
# 检查 package.json 中的平台相关配置
echo "检查包配置..."
find . -name "package.json" -exec cat {} \; | grep -i "platform\|react-native\|harmony"
Length of output: 8800
src/packages/form/doc.zh-TW.md (1)
127-127
: 补充说明很有帮助!
对 setFieldsValue
方法的说明更加清晰,提醒用户注意值会直接存储到表单状态中,并建议在不希望修改原对象时传入副本。这样可以帮助用户避免意外的副作用。
src/packages/form/doc.en-US.md (2)
128-128
: 补充了 setFieldsValue 方法的重要使用说明
对 setFieldsValue
方法的描述进行了优化,增加了关于对象修改的重要提示,这有助于开发者避免在多端开发中出现意外的数据修改问题。
129-129
: 新增了 setFieldValue 方法的文档说明
新增的 setFieldValue
方法文档完善了表单操作的 API,使开发者能够更精确地控制单个表单字段,这对于多端适配场景下的表单处理很有帮助。
src/packages/form/useform.taro.ts (4)
3-3
: 导入 merge 工具函数符合最佳实践!
merge 工具函数的引入有助于统一处理对象合并逻辑,提高代码的可维护性。
88-92
: setInitialValues 的改进实现更加合理!
使用 merge 函数来合并初始值和现有 store 是个很好的改进:
- 保持了数据的完整性
- 避免了直接引用修改
- 逻辑更清晰
122-126
: setFieldValue 方法设计简洁有效!
新增的 setFieldValue 方法具有以下优点:
- 使用泛型保证类型安全
- 复用现有的 setFieldsValue 逻辑
- 提供了更便捷的单字段更新接口
155-155
: 错误处理逻辑优化合理!
直接解构 errors 使代码更简洁,同时保持了原有功能。
src/packages/form/useform.ts (4)
3-3
: 优化:Store 更新逻辑集中化处理
引入 merge
工具函数并添加 updateStore
方法是个很好的重构,它:
- 统一了 store 更新的入口点
- 提供了更可预测的状态管理
- 降低了代码重复
Also applies to: 78-80
122-126
: 优化:类型安全性增强
新增的 setFieldValue
方法提供了更好的类型安全性,这是个很好的改进。
199-200
: 优化:重置逻辑更加可靠
使用 merge
函数来重置表单是个很好的改进,它能确保深层对象的正确重置。
240-240
: 改进:类型定义更加完整
添加 setFieldValue
到表单实例接口并修复 hook 返回类型是很好的改进。
Also applies to: 260-260
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Outside diff range and nitpick comments (13)
src/utils/to-array.ts (1)
1-7
: 实现清晰简洁,建议添加文档注释函数实现符合最佳实践,泛型类型使用恰当。建议添加 JSDoc 文档说明函数用途和参数类型。
建议添加如下文档注释:
+/** + * 将输入值转换为数组格式 + * @param value - 输入值,可以是单个值、数组或 null + * @returns 转换后的数组 + * @example + * toArray(1) // [1] + * toArray([1, 2]) // [1, 2] + * toArray(null) // [] + */ export function toArray<T>(value?: T | T[] | null): T[] {src/packages/form/form.tsx (2)
50-54
: 建议优化属性解构的顺序建议将相关的属性放在一起,提高代码的可读性。例如:
- 布局相关:
labelPosition
,starPosition
- 行为控制:
disabled
,validateTrigger
- 回调函数:
onFinish
,onFinishFailed
const { className, style, footer, children, initialValues, divider, + labelPosition, + starPosition, disabled, + validateTrigger, onFinish, onFinishFailed, - validateTrigger, - labelPosition, - starPosition, form, } = {
Line range hint
1-116
: 关于多端适配的建议根据 PR 目标,针对 RN 和 HarmonyOS 的样式选择器限制,建议:
- 考虑使用 CSS-in-JS 方案来处理样式
- 为不同平台提供独立的样式文件
- 添加平台特定的单元测试用例
src/packages/form/form.taro.tsx (2)
15-17
: 建议为新增的属性添加详细的 JSDoc 注释为了提高代码的可维护性和文档的完整性,建议为
FormProps
接口中的新属性添加详细的类型注释:export interface FormProps extends BasicComponent { footer: ReactNode initialValues: any name: string form: any + /** 是否禁用表单内的所有组件 */ disabled: boolean divider: boolean + /** 统一设置字段校验时机 */ validateTrigger: string | string[] | false
Line range hint
87-115
: 优化表单组件的多端适配实现
- 使用
TForm
替换原生form
是正确的方向,这样可以更好地处理多端兼容性问题。- Context 的更新考虑到了新增属性,保证了表单项可以正确获取状态。
建议:
- 考虑添加平台特定的样式处理
- 验证事件处理器在各平台的兼容性
建议在样式文件中添加平台特定的样式处理:
// form.scss .nut-form { // 基础样式 // RN 特定样式 :global(.rn) & { // RN 适配样式 } // HarmonyOS 特定样式 :global(.harmony) & { // HarmonyOS 适配样式 } }src/packages/formitem/formitem.tsx (4)
139-155
: 优化验证触发器处理逻辑当前实现可以更简洁,建议使用数组方法优化代码。
建议重构为:
- const validateTriggers: string[] = toArray(mergedValidateTrigger) - validateTriggers.forEach((trigger) => { - const originTrigger = controlled[trigger] - controlled[trigger] = (...args: any) => { - if (originTrigger) { - originTrigger(...args) - } - if (this.props.rules && this.props.rules.length) { - dispatch({ - name: this.props.name, - }) - } - } - }) + toArray(mergedValidateTrigger).reduce((acc, trigger) => { + const originTrigger = controlled[trigger] + acc[trigger] = (...args: any) => { + originTrigger?.(...args) + this.props.rules?.length && dispatch({ name: this.props.name }) + } + return acc + }, controlled)🧰 Tools
🪛 Biome
[error] 151-155: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
190-195
: 建议优化类名生成性能
getClassNameWithDirection
方法在渲染时多次调用,建议使用 memoization 优化性能。建议添加 memoization:
+ private classNameCache: Map<string, string> = new Map() getClassNameWithDirection(className: string) { + const cacheKey = `${className}-${this.context.labelPosition}` + if (this.classNameCache.has(cacheKey)) { + return this.classNameCache.get(cacheKey)! + } if (className && this.context.labelPosition) { - return `${className} ${className}-${this.context.labelPosition}` + const result = `${className} ${className}-${this.context.labelPosition}` + this.classNameCache.set(cacheKey, result) + return result } + this.classNameCache.set(cacheKey, className) return className }
215-224
: 建议增强标签的可访问性虽然添加了 span 包装,但可以进一步改善标签的可访问性。
建议添加 ARIA 属性:
const renderLabel = ( <> {starPosition === 'left' ? renderStar : null} - <span className="nut-form-item-labeltxt">{label}</span> + <span + className="nut-form-item-labeltxt" + aria-required={required || requiredInRules} + id={`${name}-label`} + > + {label} + </span> {starPosition === 'right' ? renderStar : null} </> )
274-278
: 建议完善禁用状态处理当前仅添加了禁用类名,建议增加更多禁用状态的处理。
建议增加以下功能:
+ const disabledClass = this.context.disabled ? 'nut-form-item-disabled' : '' return ( <React.Fragment key={this.state.resetCount}> - <div className={this.context.disabled ? 'nut-form-item-disabled' : ''}> + <div + className={disabledClass} + aria-disabled={this.context.disabled} + onClick={this.context.disabled ? (e) => e.preventDefault() : undefined} + > {this.props.noStyle ? returnChildNode : this.renderLayout(returnChildNode)} </div> </React.Fragment> )src/packages/formitem/formitem.taro.tsx (4)
Line range hint
79-89
: 优化初始值设置逻辑当前的初始值设置逻辑可以进一步优化,建议:
- 使用解构赋值简化代码
- 添加类型检查以提高代码健壮性
- const { store = {}, setInitialValues } = - this.context.formInstance.getInternal(SECRET) + const { store = {}, setInitialValues } = this.context.formInstance.getInternal(SECRET) || {} + if (!setInitialValues) return if ( - this.props.initialValue && - this.props.name && - !Object.keys(store).includes(this.props.name) + this.props.initialValue != null && + this.props.name && + !(this.props.name in store) ) { setInitialValues( { ...store, [this.props.name]: this.props.initialValue }, true ) }
140-156
: 增强验证触发器的类型安全性验证触发器的实现逻辑正确,但可以通过以下方式增强类型安全性:
- 为触发器名称定义枚举类型
- 使用类型守卫确保回调函数存在
enum ValidateTrigger { onChange = 'onChange', onBlur = 'onBlur', onFocus = 'onFocus' } type ValidateTriggerType = keyof typeof ValidateTrigger; const validateTriggers = toArray<ValidateTriggerType>(mergedValidateTrigger);🧰 Tools
🪛 Biome
[error] 152-156: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
191-196
: 优化类名生成性能
getClassNameWithDirection
方法在每次渲染时都会被调用多次。建议使用 memoization 来优化性能:+ private memoizedClassNames: Map<string, string> = new Map() getClassNameWithDirection(className: string) { + const key = `${className}-${this.context.labelPosition}` + if (this.memoizedClassNames.has(key)) { + return this.memoizedClassNames.get(key) + } if (className && this.context.labelPosition) { - return `${className} ${className}-${this.context.labelPosition}` + const result = `${className} ${className}-${this.context.labelPosition}` + this.memoizedClassNames.set(key, result) + return result } + this.memoizedClassNames.set(key, className) return className }
276-279
: 增强多端兼容性处理当前的禁用状态处理可以针对不同平台进行优化:
- RN 平台:使用
pointerEvents
属性- HarmonyOS:考虑使用原生禁用状态
+ import { Platform } from '@tarojs/taro' <View className={this.context.disabled ? 'nut-form-item-disabled' : ''} catchMove={this.context.disabled} + style={{ + ...(Platform.OS === 'rn' && this.context.disabled + ? { pointerEvents: 'none' as const } + : {}) + }} >
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (9)
src/packages/form/doc.en-US.md
(2 hunks)src/packages/form/doc.md
(2 hunks)src/packages/form/doc.taro.md
(2 hunks)src/packages/form/doc.zh-TW.md
(2 hunks)src/packages/form/form.taro.tsx
(6 hunks)src/packages/form/form.tsx
(4 hunks)src/packages/formitem/formitem.taro.tsx
(11 hunks)src/packages/formitem/formitem.tsx
(10 hunks)src/utils/to-array.ts
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
- src/packages/form/doc.en-US.md
- src/packages/form/doc.md
- src/packages/form/doc.taro.md
- src/packages/form/doc.zh-TW.md
🧰 Additional context used
🪛 Biome
src/packages/formitem/formitem.taro.tsx
[error] 152-156: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 236-238: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
src/packages/formitem/formitem.tsx
[error] 151-155: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 235-237: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
🔇 Additional comments (6)
src/packages/form/form.tsx (3)
14-16
: 新增的表单属性类型定义合理
disabled
和 validateTrigger
的类型定义符合常见表单组件的设计规范,有助于提升组件的可用性。
27-29
: 默认值设置合理
disabled
默认为false
,符合用户预期validateTrigger
默认为'onChange'
,符合常见的表单验证行为
105-109
: Context 数据结构变更需要注意兼容性
将 Context value 从单一的 formInstance
扩展为包含多个属性的对象是个重大改动。
建议:
- 确保所有子组件都已适配新的 Context 结构
- 考虑在升级指南中说明这个变更
✅ Verification successful
Let me check how these components are using the Context value by examining their implementation.
Let me check how these components are actually using the ctx value to understand the impact.
Let me check the previous implementation of the Context to understand what changed.
Context 结构变更已经得到正确处理
从代码分析来看,Context 的变更是渐进式的,从最初的 formInstance
逐步扩展到包含 labelPosition
、disabled
和 validateTrigger
。检查使用这些值的组件(checkbox)显示它们已经正确适配了新的 Context 结构,通过解构获取所需的属性。这种渐进式的改动保证了良好的兼容性。
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# 检查是否有其他组件直接使用 formInstance
ast-grep --pattern 'useContext(Context)'
Length of output: 191
Script:
#!/bin/bash
# Check checkbox component implementations
echo "=== checkbox.tsx ==="
rg -A 5 "const ctx = useContext\(Context\)" src/packages/checkbox/checkbox.tsx
echo -e "\n=== checkbox.taro.tsx ==="
rg -A 5 "const ctx = useContext\(Context\)" src/packages/checkbox/checkbox.taro.tsx
Length of output: 646
Script:
#!/bin/bash
# Search for ctx usage in checkbox components
echo "=== checkbox.tsx ctx usage ==="
rg "ctx\." src/packages/checkbox/checkbox.tsx
echo -e "\n=== checkbox.taro.tsx ctx usage ==="
rg "ctx\." src/packages/checkbox/checkbox.taro.tsx
Length of output: 882
Script:
#!/bin/bash
# Check git history for the Context implementation
git log -p src/packages/form/form.tsx | rg -A 5 -B 5 "Context.Provider"
Length of output: 3997
src/packages/form/form.taro.tsx (2)
106-110
: 验证 Context 在多端的表现一致性
需要确保 Context 的传递在 RN 和 HarmonyOS 上都能正常工作,特别是对于深层嵌套的表单项。
#!/bin/bash
# 检查 Context 的使用情况
rg "Context.Consumer" "src/packages/form*"
rg "useContext" "src/packages/form*"
28-30
: validateTrigger 的默认值需要考虑多端兼容性
考虑到在 RN 和 HarmonyOS 上的事件处理差异,建议验证 onChange
是否在所有目标平台上都能正常工作。
✅ Verification successful
validateTrigger 的默认值设置是合理的
通过代码分析,我发现:
- 在 form.taro.tsx 和 form.tsx 中,validateTrigger 的默认值都统一设置为 'onChange'
- FormItem 组件中有完整的事件处理机制,会根据 validateTrigger 自动绑定验证触发器
- 在 FormItem 的实现中,无论是 Taro 还是 Web 版本,都支持:
- 通过 props.validateTrigger 自定义触发方式
- 继承 Form 组件的 validateTrigger 配置
- 支持字符串或字符串数组形式的触发器配置
代码实现已经考虑了跨平台兼容性,并提供了灵活的配置选项,开发者可以根据具体平台需求自定义验证触发方式。因此当前的默认值设置是合理的。
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# 检查其他表单相关组件是否都支持 onChange 事件
rg -l "onChange" "src/packages/form*"
Length of output: 197
Script:
#!/bin/bash
# 搜索所有表单相关文件
fd "form" "src"
# 检查表单组件中的事件处理
rg "onChange|onBlur|onFocus" --type tsx --type ts
Length of output: 569
Script:
#!/bin/bash
# 检查表单组件在不同平台的实现
cat src/packages/form/form.taro.tsx
cat src/packages/form/form.tsx
cat src/packages/form/useform.taro.ts
cat src/packages/form/useform.ts
cat src/packages/formitem/formitem.taro.tsx
cat src/packages/formitem/formitem.tsx
Length of output: 34402
src/packages/formitem/formitem.tsx (1)
7-7
: 导入和类型定义的改进
新增的 toArray
工具函数和必需的 align
属性有助于提高代码的健壮性。
Also applies to: 38-38
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Outside diff range and nitpick comments (17)
src/utils/to-array.ts (2)
1-7
: 代码实现清晰简洁,但建议添加文档说明函数实现逻辑正确,能够妥善处理各种输入情况。不过建议添加以下改进:
+/** + * 将任意值转换为数组 + * @param value - 输入值,可以是单个值、数组、null 或 undefined + * @returns 返回数组,如果输入为空则返回空数组 + * @example + * toArray(undefined) // [] + * toArray(null) // [] + * toArray(1) // [1] + * toArray([1, 2]) // [1, 2] + */ export function toArray<T>(value?: T | T[] | null): T[] { if (value === undefined || value === null) { return [] } return Array.isArray(value) ? value : [value] }
1-1
: 建议添加单元测试用例为确保函数在各种场景下的正确性,建议添加完整的单元测试覆盖以下场景:
- 空值处理(undefined、null)
- 基本类型值(数字、字符串、布尔值)
- 对象类型值
- 数组类型值
- 嵌套数组的处理
需要我帮您生成相应的单元测试代码吗?
src/packages/form/form.tsx (3)
14-14
: 新增的表单属性类型定义合理且完整
disabled
和validateTrigger
的类型定义符合预期:
disabled: boolean
用于控制整个表单的禁用状态validateTrigger: string | string[] | false
提供了灵活的验证触发方式配置建议在类型定义中添加属性说明文档。
export interface FormProps extends BasicComponent { + /** 是否禁用表单 */ disabled: boolean divider: boolean + /** 统一设置字段校验时机 */ validateTrigger: string | string[] | falseAlso applies to: 16-16
105-109
: Context 数据结构优化建议当前 Context 值的传递方式可以进一步优化:
- 考虑将这些配置项封装到专门的配置对象中
- 使用 useMemo 优化 Context 值的性能
建议按照以下方式重构:
+const formConfig = useMemo( + () => ({ + formInstance, + labelPosition, + disabled, + validateTrigger, + }), + [formInstance, labelPosition, disabled, validateTrigger] +) <Context.Provider - value={{ formInstance, labelPosition, disabled, validateTrigger }} + value={formConfig} >
50-54
: 属性解构顺序建议建议将相关的属性放在一起,提高代码的可读性:
- 表单状态相关:
disabled
,validateTrigger
- 布局相关:
labelPosition
,starPosition
- 回调相关:
onFinish
,onFinishFailed
const { className, style, footer, children, initialValues, divider, - disabled, - onFinish, - onFinishFailed, - validateTrigger, + disabled, + validateTrigger, labelPosition, starPosition, + onFinish, + onFinishFailed, form, } = {src/packages/form/form.taro.tsx (3)
28-30
: 建议添加 validateTrigger 的类型约束
validateTrigger
的默认值设置为 'onChange' 是合理的,但建议添加类型约束以确保只能传入有效的触发方式。建议这样修改:
- validateTrigger: 'onChange', + validateTrigger: 'onChange' as 'onChange' | 'onBlur',
106-110
: 建议优化 Context 值的性能当前的 Context 值在每次渲染时都会创建新对象,这可能导致不必要的重渲染。建议使用 useMemo 优化。
建议这样修改:
+ const contextValue = React.useMemo( + () => ({ formInstance, labelPosition, disabled, validateTrigger }), + [formInstance, labelPosition, disabled, validateTrigger] + ); <Context.Provider - value={{ formInstance, labelPosition, disabled, validateTrigger }} + value={contextValue} >
Line range hint
87-115
: 建议添加多端兼容性说明
TForm
组件的实现看起来没有问题,但建议在组件上方添加注释,说明多端兼容性的注意事项,特别是在 RN 和 HarmonyOS 平台上的行为差异。建议添加如下注释:
+ /** + * Form 组件的多端适配版本 + * 注意: + * 1. RN 平台仅支持类选择器和伪元素选择器 + * 2. HarmonyOS 平台样式选择器存在限制 + * 3. 表单控件样式在不同平台可能略有差异 + */ <TFormsrc/packages/form/doc.zh-TW.md (2)
82-82
: validateTrigger 属性的文档说明需要补充更多细节建议补充以下内容:
- 支持的具体触发时机值(例如:'onChange', 'onBlur' 等)
- 当传入数组时的行为说明
- 与 Form.Item 中 validateTrigger 的优先级关系
-| validateTrigger | 統一設定字段觸發驗證的時機 | `string` \| `string[]` | `onChange` | +| validateTrigger | 統一設定字段觸發驗證的時機。支持 'onChange'、'onBlur' 等,可传入数组同时监听多个事件。Form.Item 中的 validateTrigger 优先级高于 Form 中的 validateTrigger | `string` \| `string[]` | `onChange` |
129-129
: setFieldValue 方法的泛型参数说明不足当前文档缺少了泛型参数
T
的使用说明,这对于 TypeScript 用户来说可能不够清晰。-| setFieldValue | 設定對應欄位名的值 | `<T>(name: NamePath, value: T) => void` | +| setFieldValue | 設定對應欄位名的值。泛型参数 T 用于指定字段值的类型,提供更好的类型推导 | `<T>(name: NamePath, value: T) => void` |src/packages/formitem/formitem.tsx (4)
Line range hint
109-155
: 受控组件处理逻辑的增强验证触发器的处理逻辑得到了改进,但有以下几点建议:
- 建议将验证触发器的处理逻辑抽取为独立方法
- 考虑添加错误处理,防止触发器回调执行失败影响表单状态
建议重构为:
private handleValidateTrigger = (controlled: any, trigger: string) => { const originTrigger = controlled[trigger]; controlled[trigger] = (...args: any) => { try { if (originTrigger) { originTrigger(...args); } if (this.props.rules?.length) { this.context.formInstance.getInternal(SECRET).dispatch({ name: this.props.name, }); } } catch (error) { console.error('验证触发器执行失败:', error); } }; };🧰 Tools
🪛 Biome
[error] 151-155: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
190-195
: 新增方向支持的实现
getClassNameWithDirection
方法的实现简洁有效,但建议添加空值处理。getClassNameWithDirection(className: string) { - if (className && this.context.labelPosition) { + if (!className) return ''; + if (this.context.labelPosition) { return `${className} ${className}-${this.context.labelPosition}` } return className }
Line range hint
213-278
: 布局渲染逻辑的改进布局渲染的改进很好地支持了多端适配,但有一些建议:
- 建议将必填星号的渲染逻辑抽取为独立方法
- 考虑使用 CSS-in-JS 或 CSS Modules 来避免类名冲突
建议将星号渲染逻辑抽取为:
private renderRequiredStar = () => { const { rules, required } = this.props; const requiredInRules = rules?.some((rule: any) => rule.required); if (!(required || requiredInRules)) return null; return ( <div className="nut-form-item-label-required">*</div> ); };🧰 Tools
🪛 Biome
[error] 235-237: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
274-278
: 禁用状态处理的优化使用条件类名处理禁用状态是个好方法,但建议使用 classnames 库来处理类名组合。
+ import classNames from 'classnames'; - <div className={this.context.disabled ? 'nut-form-item-disabled' : ''}> + <div className={classNames({ 'nut-form-item-disabled': this.context.disabled })}>src/packages/formitem/formitem.taro.tsx (3)
Line range hint
79-89
: 优化初始值设置的类型安全性当前的初始值设置逻辑可以增加类型检查以提高代码的健壮性。建议添加类型守卫和空值检查。
- const { store = {}, setInitialValues } = - this.context.formInstance.getInternal(SECRET) + const { store = {}, setInitialValues } = this.context.formInstance?.getInternal(SECRET) || {} + if (!setInitialValues) { + console.warn('[NutUI] FormItem: 未找到 setInitialValues 方法') + return + }
191-196
: 优化类名生成逻辑
getClassNameWithDirection
方法在每次渲染时都会被调用多次,建议:
- 缓存类名计算结果
- 使用条件表达式替代字符串模板
getClassNameWithDirection(className: string) { - if (className && this.context.labelPosition) { - return `${className} ${className}-${this.context.labelPosition}` - } - return className + const { labelPosition } = this.context + return className && labelPosition + ? [className, `${className}-${labelPosition}`].join(' ') + : className }Also applies to: 229-229
276-283
: 改进禁用状态的可访问性当前禁用状态的实现可以增加以下改进:
- 添加
aria-disabled
属性- 确保禁用状态下的颜色对比度符合可访问性标准
- 添加适当的鼠标样式
<View className={this.context.disabled ? 'nut-form-item-disabled' : ''} catchMove={this.context.disabled} + aria-disabled={this.context.disabled} + style={this.context.disabled ? { cursor: 'not-allowed' } : undefined} >
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (9)
src/packages/form/doc.en-US.md
(2 hunks)src/packages/form/doc.md
(2 hunks)src/packages/form/doc.taro.md
(2 hunks)src/packages/form/doc.zh-TW.md
(2 hunks)src/packages/form/form.taro.tsx
(6 hunks)src/packages/form/form.tsx
(4 hunks)src/packages/formitem/formitem.taro.tsx
(11 hunks)src/packages/formitem/formitem.tsx
(10 hunks)src/utils/to-array.ts
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- src/packages/form/doc.en-US.md
- src/packages/form/doc.md
- src/packages/form/doc.taro.md
🧰 Additional context used
🪛 Biome
src/packages/formitem/formitem.taro.tsx
[error] 152-156: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 236-238: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
src/packages/formitem/formitem.tsx
[error] 151-155: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 235-237: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
🔇 Additional comments (4)
src/packages/form/form.tsx (1)
27-29
: 默认属性值设置合理
默认值的设置符合常见使用场景:
disabled: false
- 默认启用表单validateTrigger: 'onChange'
- 采用实时验证模式
src/packages/form/form.taro.tsx (1)
2-2
: 新增的跨端适配更改看起来不错!
使用 @tarojs/components
的 TForm
组件替代原生 form 元素是正确的选择,这样可以更好地支持 RN 和 HarmonyOS 平台。新增的 disabled
和 validateTrigger
属性也有助于提升表单的可控性。
Also applies to: 15-17
src/packages/form/doc.zh-TW.md (1)
128-128
: setFieldsValue 方法的说明很好地提醒了对象修改的注意事项
文档中清晰说明了该方法会直接修改表单状态,并提醒用户注意对象引用的问题,这对于防止意外的状态修改很有帮助。
src/packages/formitem/formitem.tsx (1)
Line range hint 78-92
: 表单实例访问模式的优化
通过 formInstance.getInternal
统一访问内部方法提高了代码的内聚性,这是个很好的改进。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Outside diff range and nitpick comments (7)
src/packages/form/demos/taro/demo1.tsx (1)
Line range hint
21-31
: 验证规则存在潜在问题当前的验证规则存在以下问题:
- max 限制为 5 个字符,但自定义 validator 却要求长度大于 5,这是相互矛盾的
- 验证失败时没有相应的错误提示信息
建议修改为:
rules={[ { max: 5, message: '字段A不能超过5个字' }, { required: true, message: '请输入字段A' }, { validator: ( ruleCfg: FormItemRuleWithoutValidator, value: string ) => { - return value?.length > 5 + return value?.length <= 5 }, + message: '字段A不能超过5个字' }, ]}src/packages/formitem/formitem.tsx (3)
144-160
: 建议重构验证触发器的处理逻辑当前验证触发器的处理逻辑较为复杂,建议将其提取为独立的方法以提高可维护性。
建议重构为:
+ private bindValidationTriggers(controlled: any) { + const validateTriggers = toArray(this.props.validateTrigger || this.context.validateTrigger) + validateTriggers.forEach((trigger) => { + const originTrigger = controlled[trigger] + controlled[trigger] = (...args: any) => { + if (originTrigger) originTrigger(...args) + if (this.props.rules?.length) { + this.context.formInstance.getInternal(SECRET).dispatch({ + name: this.props.name, + }) + } + } + }) + return controlled + }🧰 Tools
🪛 GitHub Check: codecov/patch
[warning] 160-160: src/packages/formitem/formitem.tsx#L160
Added line #L160 was not covered by tests
195-200
: 建议添加类型定义
getClassNameWithDirection
方法缺少返回值类型定义,建议添加类型注解以增强代码的类型安全性。- getClassNameWithDirection(className: string) { + getClassNameWithDirection(className: string): string {
279-283
: 建议优化条件渲染逻辑当前的条件渲染逻辑可以更简洁。建议使用条件类名而不是额外的包装层。
- <div className={this.context.disabled ? 'nut-form-item-disabled' : ''}> - {this.props.noStyle - ? returnChildNode - : this.renderLayout(returnChildNode)} - </div> + {this.props.noStyle ? ( + <div className={classNames({ 'nut-form-item-disabled': this.context.disabled })}> + {returnChildNode} + </div> + ) : ( + this.renderLayout(returnChildNode) + )}src/packages/formitem/formitem.taro.tsx (3)
115-120
: 优化警告信息处理当前的警告信息处理已经有所改进,但建议进一步优化:
- 使用更规范的错误信息格式
- 添加更多上下文信息
- 考虑使用开发环境变量
建议应用以下修改:
if (process.env.NODE_ENV !== 'production') { - console.warn( - '[NutUI] FormItem:', - '请通过 initialValue 设置初始值,而不是 defaultValue' - ) + console.warn( + `[NutUI] FormItem "${name}": 检测到使用 defaultValue 设置初始值。` + + '为保持一致性,请使用 initialValue 代替 defaultValue。\n' + + '详情请参考文档:https://nutui.jd.com/react/2x/#/zh-CN/component/form' + ) }
196-201
: 优化类名处理逻辑当前的类名处理逻辑可以进一步优化:
- 使用条件判断简化
- 添加类型检查
- 考虑使用类名工具库
建议应用以下修改:
- getClassNameWithDirection(className: string) { - if (className && this.context.labelPosition) { - return `${className} ${className}-${this.context.labelPosition}` - } - return className - } + getClassNameWithDirection(className?: string): string { + if (!className) return '' + const { labelPosition } = this.context + return labelPosition + ? `${className} ${className}-${labelPosition}` + : className + }
281-288
: 改进禁用状态处理当前的禁用状态处理可以进一步优化:
- 使用语义化的 ARIA 属性
- 添加更多视觉反馈
- 优化事件处理
建议应用以下修改:
<View - className={this.context.disabled ? 'nut-form-item-disabled' : ''} - catchMove={this.context.disabled} + className={classNames({ + 'nut-form-item-disabled': this.context.disabled, + 'nut-form-item-wrapper': true + })} + catchMove={this.context.disabled} + aria-disabled={this.context.disabled} + role="group" > {this.props.noStyle ? returnChildNode : this.renderLayout(returnChildNode)} </View>
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (5)
src/packages/form/demos/taro/demo1.tsx
(2 hunks)src/packages/form/useform.taro.ts
(8 hunks)src/packages/form/useform.ts
(7 hunks)src/packages/formitem/formitem.taro.tsx
(10 hunks)src/packages/formitem/formitem.tsx
(10 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- src/packages/form/useform.taro.ts
- src/packages/form/useform.ts
🧰 Additional context used
🪛 Biome
src/packages/formitem/formitem.taro.tsx
[error] 242-243: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
src/packages/formitem/formitem.tsx
[error] 241-242: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
🪛 GitHub Check: codecov/patch
src/packages/formitem/formitem.tsx
[warning] 125-125: src/packages/formitem/formitem.tsx#L125
Added line #L125 was not covered by tests
[warning] 160-160: src/packages/formitem/formitem.tsx#L160
Added line #L160 was not covered by tests
🔇 Additional comments (4)
src/packages/form/demos/taro/demo1.tsx (2)
2-2
: 优化导入语句
从 @nutui/nutui-react-taro
的导入已经优化,符合组件按需加载的最佳实践。
50-54
: 建议验证 TextArea 样式在多端的兼容性
添加 padding 为 0 的样式可能会在不同平台上产生不一致的显示效果。建议:
- 验证在 React Native 和 HarmonyOS 上的表现
- 考虑使用设计规范中的标准间距值
src/packages/formitem/formitem.tsx (1)
114-119
: 开发环境警告提示的改进
添加了开发环境下的警告提示,帮助开发者正确使用 initialValue
而不是 defaultValue
,这是一个很好的改进。
src/packages/formitem/formitem.taro.tsx (1)
39-40
:
需要为必需的 align 属性提供默认值
将 align
从可选属性改为必需属性是一个破坏性更改,可能会影响现有代码。建议:
- 在
defaultProps
中添加默认值 - 或者保持为可选属性,但在使用时进行空值检查
建议应用以下修改:
- align: 'flex-start' | 'center' | 'flex-end'
+ align?: 'flex-start' | 'center' | 'flex-end'
const defaultProps = {
...ComponentDefaults,
required: false,
name: '',
label: '',
rules: [{ required: false, message: '' }],
errorMessageAlign: 'left',
shouldUpdate: false,
noStyle: false,
+ align: 'center',
} as FormItemProps
Likely invalid or redundant comment.
# Conflicts: # src/packages/input/input.taro.tsx
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Outside diff range and nitpick comments (12)
src/packages/formitem/formitem.tsx (6)
114-119
: 开发环境警告提示很有帮助良好的开发者体验改进,清晰地指导开发者使用
initialValue
而不是defaultValue
。建议考虑添加文档链接,帮助开发者更好地理解这个最佳实践。
144-160
: 建议增强验证触发器的错误处理虽然验证触发器的实现更加健壮,但建议添加以下改进:
- 对无效的触发器类型进行错误处理
- 验证失败时提供更详细的错误信息
建议添加如下错误处理:
const validateTriggers: string[] = toArray(mergedValidateTrigger) +const validTriggers = ['onChange', 'onBlur', 'onFocus'] +validateTriggers.forEach((trigger) => { + if (!validTriggers.includes(trigger)) { + console.warn(`[NutUI] FormItem: 不支持的验证触发器类型 "${trigger}"`) + return + } const originTrigger = controlled[trigger] // ... 其余代码 })
195-200
: 建议增加空值检查
getClassNameWithDirection
方法的实现简洁,但建议添加防御性编程:getClassNameWithDirection(className: string) { - if (className && this.context.labelPosition) { + if (!className) return '' + if (className && this.context?.labelPosition) { return `${className} ${className}-${this.context.labelPosition}` } return className }
226-229
: 标签渲染结构优化得当新的标签结构支持星号位置自定义,提升了灵活性。建议进一步优化无障碍体验:
-<span className="nut-form-item-labeltxt"> +<span className="nut-form-item-labeltxt" role="label" aria-required={required}> {starPosition === 'left' ? renderStar : null} {label} </span>
281-285
: 建议增强禁用状态处理禁用状态的实现可以更加完善:
-<div className={this.context.disabled ? 'nut-form-item-disabled' : ''}> +<div + className={this.context.disabled ? 'nut-form-item-disabled' : ''} + aria-disabled={this.context.disabled} + onClick={this.context.disabled ? (e) => e.preventDefault() : undefined} +> {this.props.noStyle ? returnChildNode : this.renderLayout(returnChildNode)} </div>
Line range hint
1-289
: 建议改进组件架构当前组件承担了多个职责,建议考虑以下架构改进:
- 将表单验证逻辑抽离为独立的 hook
- 将样式处理逻辑抽离为独立的工具函数
- 考虑使用 React.memo 优化渲染性能
是否需要我协助创建相关重构的 GitHub issue?
🧰 Tools
🪛 Biome
[error] 243-244: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
src/packages/formitem/formitem.taro.tsx (4)
Line range hint
79-93
: 建议增加错误处理机制在访问 formInstance 方法时缺少错误处理,可能导致运行时异常。
建议添加错误处理:
- const { store = {}, setInitialValues } = - this.context.formInstance.getInternal(SECRET) + const formInstance = this.context.formInstance + if (!formInstance) { + console.error('[NutUI] FormItem: formInstance 未找到,请确保在 Form 组件内使用') + return + } + const { store = {}, setInitialValues } = formInstance.getInternal(SECRET)
196-201
: 建议增强 getClassNameWithDirection 方法的健壮性当前实现可以进一步优化以处理边缘情况。
建议改进实现:
- getClassNameWithDirection(className: string) { - if (className && this.context.labelPosition) { - return `${className} ${className}-${this.context.labelPosition}` - } - return className - } + getClassNameWithDirection(className: string) { + if (!className) return '' + const position = this.context.labelPosition + return position + ? `${className} ${className}-${position}`.trim() + : className + }
283-290
: 建议增加无障碍支持当组件处于禁用状态时,应该添加适当的 ARIA 属性以提升可访问性。
建议添加无障碍属性:
<View className={this.context.disabled ? 'nut-form-item-disabled' : ''} catchMove={this.context.disabled} + aria-disabled={this.context.disabled} + role="group" > {this.props.noStyle ? returnChildNode : this.renderLayout(returnChildNode)} </View>
219-221
: 建议增加错误消息的自定义能力当前错误消息展示方式较为固定,建议提供更灵活的自定义选项。
建议添加错误消息渲染函数属性:
+ interface FormItemProps { + // ... 其他属性 + errorMessageRender?: (error: string) => React.ReactNode + } const item = name ? this.context.formInstance.errors[name] : [] + const errorMessage = item?.[0]?.message + const renderedError = this.props.errorMessageRender + ? this.props.errorMessageRender(errorMessage) + : errorMessagesrc/packages/formitem/formitem.scss (2)
21-27
: 注意必填标识的定位方式在
&-label-required
中使用了position: absolute;
和left: -10px;
进行定位。建议在不同屏幕尺寸和浏览器下测试,确保必填标识不会出现错位或覆盖其他元素的情况。
125-130
: 调整左对齐必填项标识的样式新增
.nut-form-item-label-left-required
类,使用绝对定位和left: 0.1em;
,建议在多语言和不同浏览器环境下测试,确保必填标识的位置准确无误。
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (5)
scripts/rn/copy-file.js
(1 hunks)src/config.json
(2 hunks)src/packages/formitem/formitem.scss
(4 hunks)src/packages/formitem/formitem.taro.tsx
(10 hunks)src/packages/formitem/formitem.tsx
(10 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- scripts/rn/copy-file.js
- src/config.json
🧰 Additional context used
🪛 Biome
src/packages/formitem/formitem.taro.tsx
[error] 244-245: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
src/packages/formitem/formitem.tsx
[error] 243-244: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
🔇 Additional comments (16)
src/packages/formitem/formitem.tsx (1)
7-7
: 导入 toArray 工具函数是合理的
新增的 toArray 工具函数用于处理验证触发器数组,这是一个良好的实践。
src/packages/formitem/formitem.taro.tsx (1)
39-39
:
需要为必需的 align 属性提供默认值
将 align
从可选属性改为必需属性是一个破坏性更改。为了确保向后兼容性,建议:
- 在 defaultProps 中添加默认值
- 或者保持为可选属性
建议应用以下修改:
- align: 'flex-start' | 'center' | 'flex-end'
+ align?: 'flex-start' | 'center' | 'flex-end'
如果确实需要设为必需属性,请在 defaultProps 中添加:
const defaultProps = {
...ComponentDefaults,
required: false,
name: '',
label: '',
rules: [{ required: false, message: '' }],
errorMessageAlign: 'left',
shouldUpdate: false,
noStyle: false,
+ align: 'center', // 添加默认值
} as FormItemProps
Likely invalid or redundant comment.
src/packages/formitem/formitem.scss (14)
4-6
: 新增禁用状态样式
添加了 &-disabled
样式,使用 opacity: 0.4;
和 pointer-events: none;
,正确地实现了元素在禁用状态下的视觉效果和交互限制。
10-11
: 调整标签的布局样式
在 .nut-form-item-label
中添加了 display: flex;
和 flex-direction: row;
,有助于标签内容水平排列,提升布局的一致性。
16-16
: 优化标签的弹性布局
增加了 flex: 0 0 auto;
,确保标签部分不会因为内容过长而压缩或拉伸,保持其原有宽度,增强布局稳定性。
21-27
: 新增必填项标签样式
添加了 &-label-required
类,设置了必填项标识的颜色、间距和定位,使必填项在表单中更加醒目。
28-31
: 新增标签文本样式类
引入了 .nut-form-item-labeltxt
类,定义了标签文本的字体大小和高度,有助于统一标签文本的样式。
34-34
: 调整表单主体的布局
在 .nut-form-item-body
中添加了 display: flex;
,确保内部元素能够正确地使用弹性布局,提升布局可靠性。
111-117
: 新增右对齐标签样式
添加了 .nut-form-item-label-right
类,通过 justify-content: flex-end;
和 padding-right: 24px;
实现标签内容的右对齐,满足特定布局需求。
119-123
: 新增左对齐标签样式
引入了 .nut-form-item-label-left
类,设置了 position: relative;
和 padding-left: 12px;
,用于左对齐标签,方便布局定制。
132-136
: 新增顶部布局样式
添加了 .nut-form-item-top
类,使用 flex-direction: column;
和 align-items: flex-start;
,实现表单项的垂直排列,适用于移动端等需要竖向布局的场景。
138-142
: 调整顶部布局的标签样式
引入了 .nut-form-item-label-top
类,设置了 padding-bottom: 4px;
,为标签和输入区域提供适当的间距,提升可读性。
144-147
: 调整顶部布局的主体样式
新增 .nut-form-item-body-top
类,移除了左边距并设置宽度为 100%,确保输入区域在垂直布局下占满可用空间。
149-154
: RTL 模式下右布局的标签样式调整
针对 RTL(右到左)语言环境,在 .form-layout-right
下调整 .nut-form-item-label
的样式,修改了文本对齐和内边距,确保在 RTL 环境下显示正确。
156-166
: RTL 模式下左布局的标签样式调整
为 .form-layout-left
在 RTL 环境下的标签和必填标识进行了样式调整,修正了文本对齐、内边距和必填标识的位置,确保布局在 RTL 环境下的正确性。
168-178
: RTL 模式下顶部布局的样式调整
针对 .form-layout-top
在 RTL 环境下的标签和主体部分,优化了内外边距设置,确保垂直布局在不同语言环境下的一致性和正确性。
@@ -179,13 +185,20 @@ export class FormItem extends React.Component< | |||
|
|||
onStoreChange = (type?: string) => { | |||
if (type === 'reset') { | |||
this.context.errors[this.props.name as string] = [] | |||
this.context.formInstance.errors[this.props.name as string] = [] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
避免直接修改错误数组
直接修改 errors 数组可能导致意外的副作用,建议使用适当的状态管理方法:
-this.context.formInstance.errors[this.props.name as string] = []
+this.context.formInstance.setErrors(this.props.name as string, [])
Committable suggestion skipped: line range outside the PR's diff.
@@ -58,7 +58,7 @@ export class FormItem extends React.Component< | |||
|
|||
static contextType: any = Context | |||
|
|||
declare context: React.ContextType<typeof Context> | |||
context!: React.ContextType<typeof Context> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
建议改进类型声明的安全性
使用非空断言操作符 (!) 可能导致运行时错误。建议添加适当的类型检查。
建议采用以下方式之一:
- 在构造函数中验证 context:
constructor(props: FormItemProps) {
super(props)
if (!this.context) {
throw new Error('FormItem 必须在 Form 组件内使用')
}
this.componentRef = React.createRef()
this.state = {
resetCount: 1,
}
}
- 或者使用可选链操作符:
- context!: React.ContextType<typeof Context>
+ context?: React.ContextType<typeof Context>
const mergedValidateTrigger = | ||
validateTrigger || this.context.validateTrigger | ||
|
||
const validateTriggers: string[] = toArray(mergedValidateTrigger) | ||
validateTriggers.forEach((trigger) => { | ||
const originTrigger = controlled[trigger] | ||
controlled[trigger] = (...args: any) => { | ||
if (originTrigger) { | ||
originTrigger(...args) | ||
} | ||
}) | ||
} | ||
if (this.props.rules && this.props.rules.length) { | ||
dispatch({ | ||
name: this.props.name, | ||
}) | ||
} | ||
} | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
优化验证触发器实现以提升性能
当前实现在每次渲染时都会重新创建验证函数,这可能影响性能。
建议使用 React.useCallback 优化:
const createValidationHandler = React.useCallback(
(trigger: string) => {
const originTrigger = controlled[trigger]
return (...args: any) => {
originTrigger?.(...args)
if (this.props.rules?.length) {
dispatch({ name: this.props.name })
}
}
},
[this.props.rules, this.props.name, dispatch]
)
const validateTriggers = React.useMemo(() => {
const mergedValidateTrigger = validateTrigger ?? this.context.validateTrigger
return toArray(mergedValidateTrigger)
}, [validateTrigger, this.context.validateTrigger])
validateTriggers.forEach((trigger) => {
controlled[trigger] = createValidationHandler(trigger)
})
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
可以先处理下conflicts和CI
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
壳工程升级后,可以看一下之前harmony问题是否还存在
# Conflicts: # src/packages/form/form.harmony.css # src/packages/formitem/formitem.harmony.css
升级鸿蒙又不行了,暂时转到 draft 状态 |
由于 RN 和 鸿蒙的选择器只能支持 类选择、多类选择器和伪元素选择器,所以无法实现通过 form 控制 input textarea 等的样式,需要从视觉层面来进行一些组件样式的修复。这样可以确保放到 form 中样式表现良好。
Summary by CodeRabbit
新功能
formitem
组件的支持,增强了文件复制和修改操作的功能。Input
、InputNumber
、Range
、Switch
和TextArea
组件,并更新了多个组件的版本。disabled
和validateTrigger
属性,以增强表单的功能和控制。setFieldValue
方法,允许通过名称设置特定字段的值。文档
Form
组件的文档,增加了validateTrigger
属性的描述和新方法setFieldValue
的介绍。样式