Skip to content

Conversation

oasis-cloud
Copy link
Collaborator

@oasis-cloud oasis-cloud commented Feb 20, 2025

Summary by CodeRabbit

  • 新功能
    • 引入异步预处理回调功能(beforeChange),在输入变更前对数值进行异步校验和处理,提升了交互反馈。
    • 扩大了数字输入范围(如将最小值从 -6 调整为 -9999),满足更多业务需求。
  • 文档更新
    • 更新了组件文档,新增说明新属性及更新的样式变量,为用户提供更多自定义调整选项。

Copy link

coderabbitai bot commented Feb 20, 2025

Important

Review skipped

More than 25% of the files skipped due to max files limit. The review is being skipped to prevent a low-quality review.

149 files out of 356 files are above the max files limit of 200.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

此次变更主要围绕 InputNumber 组件的异步事件处理能力的改进。测试文件中增加了 async/await 及 act 包裹以确保事件处理正确执行;演示文件中用新的 beforeChange 替换了 onChange 方法,实现延时预处理和更广数值范围;文档则更新了属性说明,CSS 变量值及新增了圆角属性;组件实现文件移除了 async 属性,并将相关函数改为异步,优化了数值更新逻辑。

Changes

文件 修改内容
src/packages/inputnumber/__tests__/inputnumber.spec.tsx 为多处 fireEvent 包裹 async/await act,调整断言方法从 toBeCalled()toHaveBeenCalled()
src/packages/inputnumber/demos/h5/demo8.tsx
src/packages/inputnumber/demos/taro/demo8.tsx
替换 onChange 为 beforeChange 实现异步预处理,更新 min 属性至 -9999(Taro demo 中移除 Cell 组件及命名修正)。
src/packages/inputnumber/doc*.md
(包括 doc.en-US.md, doc.md, doc.taro.md, doc.zh-TW.md)
文档更新:标记 async 为弃用,添加 beforeChange 属性,更新 select 属性版本说明,并调整 CSS 变量(包括新增按钮圆角)。
src/packages/inputnumber/inputnumber.taro.tsx
src/packages/inputnumber/inputnumber.tsx
实现改进:添加 beforeChange 属性,移除 async 属性,将 update、handleReduce、handlePlus、handleInputChange 等函数改为异步,更新 onChange 方法签名及格式化逻辑。

Sequence Diagram(s)

sequenceDiagram
  participant U as 用户
  participant IN as InputNumber 组件
  participant BC as beforeChange 回调
  participant ST as 状态更新

  U->>IN: 发起输入或点击事件
  IN->>BC: 调用 beforeChange 检查
  BC-->>IN: 返回 Boolean/Promise 结果
  alt 检查通过
      IN->>ST: 更新输入值并触发 onChange
  else 检查失败
      IN-->>U: 保持原值,不执行更新
  end
Loading

Possibly related PRs

Suggested reviewers

  • xiaoyatong
  • Alex-huxiyang

Poem

小兔跳跃在代码间,
异步预处理轻松先。
测试加 await 不打盹,
文档更新画新篇。
活力满满稳步前进 🐰✨


🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

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)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions github-actions bot added action:review This PR needs more reviews (less than 2 approvals) 3.x Target branch 3.x labels Feb 20, 2025
Copy link

codecov bot commented Feb 20, 2025

Codecov Report

Attention: Patch coverage is 98.11321% with 1 line in your changes missing coverage. Please review.

Project coverage is 86.29%. Comparing base (f74b3c1) to head (e38661d).
Report is 1 commits behind head on feat_v3.x.

Files with missing lines Patch % Lines
src/packages/inputnumber/inputnumber.tsx 98.11% 1 Missing ⚠️
Additional details and impacted files
@@              Coverage Diff              @@
##           feat_v3.x    #3006      +/-   ##
=============================================
+ Coverage      86.18%   86.29%   +0.10%     
=============================================
  Files            279      279              
  Lines          18260    18225      -35     
  Branches        2778     2775       -3     
=============================================
- Hits           15738    15727      -11     
+ Misses          2517     2493      -24     
  Partials           5        5              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (8)
src/packages/inputnumber/inputnumber.tsx (3)

128-158: 异步函数 update 逻辑清晰,但可优化类型声明。
当前 calcNextValue 的实参类型均为 any,可能影响可读性和可维护性。

可在函数定义中增加更具体的类型:

- const calcNextValue = (current: any, stepValue: any, symbol: number) => {
+ const calcNextValue = (current: number | null | string, stepValue: number | string, symbol: number) => {

159-193: 行 191 逻辑尚未被测试覆盖。
增加一个模拟输入数值边界、触发 onChange 回调的单元测试用例,可提升测试覆盖率。

需要协助添加测试用例吗?可以提供示例测试脚本。

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 191-191: src/packages/inputnumber/inputnumber.tsx#L191
Added line #L191 was not covered by tests


206-206: 建议使用可选链替代 onBlur && onBlur(e)
这是更加简洁的写法,符合现代 JavaScript 语法习惯。

- onBlur && onBlur(e)
+ onBlur?.(e)
🧰 Tools
🪛 Biome (1.9.4)

[error] 206-206: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

src/packages/inputnumber/inputnumber.taro.tsx (1)

209-209: 建议使用可选链替代 onBlur && onBlur(e)
与主仓库中其他类似写法保持一致。

- onBlur && onBlur(e)
+ onBlur?.(e)
🧰 Tools
🪛 Biome (1.9.4)

[error] 209-209: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

src/packages/inputnumber/demos/h5/demo8.tsx (1)

10-18: beforeChange 中使用 setTimeout 与 Toast 搭配演示异步场景。
目前提示文字“2秒后更改”与 500ms 延时略有差别,可适当统一。

- Toast.show({ icon: 'loading', content: '异步演示2秒后更改' })
- setTimeout(() => { ... }, 500)
+ Toast.show({ icon: 'loading', content: '异步演示0.5秒后更改' })
+ setTimeout(() => { ... }, 500)
src/packages/inputnumber/demos/taro/demo8.tsx (1)

32-38: 建议优化 InputNumber 组件的属性设置

考虑添加错误处理以提高代码健壮性。

 <InputNumber
   value={inputValue}
   min={-9999}
+  onError={(error) => {
+    toastShow(error.message, 'fail')
+  }}
   beforeChange={beforeChange}
   onChange={(value) => setInputValue(Number(value))}
   onOverlimit={overlimit}
 />
src/packages/inputnumber/__tests__/inputnumber.spec.tsx (1)

174-185: 建议完善溢出测试用例

当前的溢出测试可以更全面。

 test('should overlimit when input', async () => {
   const overlimit = vi.fn()
+  const beforeChange = vi.fn().mockResolvedValue(true)
   const { container } = render(
-    <InputNumber defaultValue={2} max={100} onOverlimit={overlimit} />
+    <InputNumber
+      defaultValue={2}
+      max={100}
+      onOverlimit={overlimit}
+      beforeChange={beforeChange}
+    />
   )
   const input = container.querySelectorAll('input')[0]
   input.value = '200'
   await act(async () => {
     fireEvent.input(input)
   })
   expect(overlimit).toBeCalled()
+  expect(beforeChange).toBeCalled()
 })
src/packages/inputnumber/doc.md (1)

143-153: CSS 变量更新与语言表达建议
CSS 变量的默认值已更新,并新增了 --nutui-inputnumber-button-border-radius 变量,整体符合设计更新要求。同时,文档中部分描述如“input的宽度”等使用了英文术语“input”。建议考虑将其替换为更符合中文表达的“输入框”,以提高语义一致性和用户的理解。

🧰 Tools
🪛 LanguageTool

[locale-violation] ~143-~143: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...-- | --- | --- | | --nutui-inputnumber-input-width | 数字输入框中input的宽度 | 40px | | --...

(GL_BARBARISM_REPLACE)


[locale-violation] ~144-~144: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...ut的宽度 | 40px | | --nutui-inputnumber-input-height | 数字输入框中input的高度 | 24px | | -...

(GL_BARBARISM_REPLACE)


[locale-violation] ~145-~145: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...ut的高度 | 24px | | --nutui-inputnumber-input-background-color | 数字输入框中input的背景颜色 | `...

(GL_BARBARISM_REPLACE)


[locale-violation] ~145-~145: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...| 24px | | --nutui-inputnumber-input-background-color | 数字输入框中input的背景颜色 | `$color-back...

(GL_BARBARISM_REPLACE)


[locale-violation] ~145-~145: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...t-background-color | 数字输入框中input的背景颜色 | $color-background | | --nutui-inputnumber-input-font-co...

(GL_BARBARISM_REPLACE)


[locale-violation] ~146-~146: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...or-background| | \--nutui-inputnumber-input-font-color | 数字输入框中input的字号颜色 |$color...

(GL_BARBARISM_REPLACE)


[locale-violation] ~147-~147: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...$color-title | | --nutui-inputnumber-input-font-size | 数字输入框中input的字号大小 | 14px |...

(GL_BARBARISM_REPLACE)


[locale-violation] ~148-~148: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...的字号大小 | 14px | | --nutui-inputnumber-input-border | 数字输入框中input的border值 | 0 | | ...

(GL_BARBARISM_REPLACE)


[locale-violation] ~149-~149: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...的border值 | 0 | | --nutui-inputnumber-input-border-radius | 数字输入框中input的圆角 | 6px ...

(GL_BARBARISM_REPLACE)


[locale-violation] ~150-~150: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...put的圆角 | 6px | | --nutui-inputnumber-input-margin | 数字输入框中input的margin值 | 0 | | ...

(GL_BARBARISM_REPLACE)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a5014bf and adf3f0f.

📒 Files selected for processing (9)
  • src/packages/inputnumber/__tests__/inputnumber.spec.tsx (8 hunks)
  • src/packages/inputnumber/demos/h5/demo8.tsx (1 hunks)
  • src/packages/inputnumber/demos/taro/demo8.tsx (1 hunks)
  • src/packages/inputnumber/doc.en-US.md (2 hunks)
  • src/packages/inputnumber/doc.md (2 hunks)
  • src/packages/inputnumber/doc.taro.md (2 hunks)
  • src/packages/inputnumber/doc.zh-TW.md (2 hunks)
  • src/packages/inputnumber/inputnumber.taro.tsx (8 hunks)
  • src/packages/inputnumber/inputnumber.tsx (7 hunks)
🧰 Additional context used
🪛 LanguageTool
src/packages/inputnumber/doc.zh-TW.md

[locale-violation] ~135-~135: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...-- | --- | --- | | --nutui-inputnumber-input-width | 數字輸入框中input的寬度 | 40px | | --...

(GL_BARBARISM_REPLACE)


[locale-violation] ~136-~136: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...ut的寬度 | 40px | | --nutui-inputnumber-input-height | 數字輸入框中input的高度 | 24px | | -...

(GL_BARBARISM_REPLACE)


[locale-violation] ~137-~137: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...ut的高度 | 24px | | --nutui-inputnumber-input-background-color | 數字輸入框中input的背景顏色 | `...

(GL_BARBARISM_REPLACE)


[locale-violation] ~137-~137: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...| 24px | | --nutui-inputnumber-input-background-color | 數字輸入框中input的背景顏色 | `$color-back...

(GL_BARBARISM_REPLACE)


[locale-violation] ~137-~137: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...t-background-color | 數字輸入框中input的背景顏色 | $color-background | | --nutui-inputnumber-input-font-co...

(GL_BARBARISM_REPLACE)


[locale-violation] ~138-~138: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...or-background| | \--nutui-inputnumber-input-font-color | 數字輸入框中input的字號顏色 |$color...

(GL_BARBARISM_REPLACE)


[locale-violation] ~139-~139: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...$color-title | | --nutui-inputnumber-input-font-size | 數字輸入框中input的字號大小 | 14px |...

(GL_BARBARISM_REPLACE)


[locale-violation] ~140-~140: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...的字號大小 | 14px | | --nutui-inputnumber-input-border | 數字輸入框中input的border值 | 0 | | ...

(GL_BARBARISM_REPLACE)


[locale-violation] ~141-~141: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...的border值 | 0 | | --nutui-inputnumber-input-border-radius | 數字輸入框中input的圓角 | 6px ...

(GL_BARBARISM_REPLACE)


[locale-violation] ~142-~142: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...put的圓角 | 6px | | --nutui-inputnumber-input-margin | 數字輸入框中input的margin值 | 0 | | ...

(GL_BARBARISM_REPLACE)

src/packages/inputnumber/doc.md

[locale-violation] ~143-~143: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...-- | --- | --- | | --nutui-inputnumber-input-width | 数字输入框中input的宽度 | 40px | | --...

(GL_BARBARISM_REPLACE)


[locale-violation] ~144-~144: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...ut的宽度 | 40px | | --nutui-inputnumber-input-height | 数字输入框中input的高度 | 24px | | -...

(GL_BARBARISM_REPLACE)


[locale-violation] ~145-~145: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...ut的高度 | 24px | | --nutui-inputnumber-input-background-color | 数字输入框中input的背景颜色 | `...

(GL_BARBARISM_REPLACE)


[locale-violation] ~145-~145: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...| 24px | | --nutui-inputnumber-input-background-color | 数字输入框中input的背景颜色 | `$color-back...

(GL_BARBARISM_REPLACE)


[locale-violation] ~145-~145: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...t-background-color | 数字输入框中input的背景颜色 | $color-background | | --nutui-inputnumber-input-font-co...

(GL_BARBARISM_REPLACE)


[locale-violation] ~146-~146: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...or-background| | \--nutui-inputnumber-input-font-color | 数字输入框中input的字号颜色 |$color...

(GL_BARBARISM_REPLACE)


[locale-violation] ~147-~147: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...$color-title | | --nutui-inputnumber-input-font-size | 数字输入框中input的字号大小 | 14px |...

(GL_BARBARISM_REPLACE)


[locale-violation] ~148-~148: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...的字号大小 | 14px | | --nutui-inputnumber-input-border | 数字输入框中input的border值 | 0 | | ...

(GL_BARBARISM_REPLACE)


[locale-violation] ~149-~149: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...的border值 | 0 | | --nutui-inputnumber-input-border-radius | 数字输入框中input的圆角 | 6px ...

(GL_BARBARISM_REPLACE)


[locale-violation] ~150-~150: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...put的圆角 | 6px | | --nutui-inputnumber-input-margin | 数字输入框中input的margin值 | 0 | | ...

(GL_BARBARISM_REPLACE)

src/packages/inputnumber/doc.taro.md

[locale-violation] ~134-~134: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...-- | --- | --- | | --nutui-inputnumber-input-width | 数字输入框中input的宽度 | 40px | | --...

(GL_BARBARISM_REPLACE)


[locale-violation] ~135-~135: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...ut的宽度 | 40px | | --nutui-inputnumber-input-height | 数字输入框中input的高度 | 24px | | -...

(GL_BARBARISM_REPLACE)


[locale-violation] ~136-~136: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...ut的高度 | 24px | | --nutui-inputnumber-input-background-color | 数字输入框中input的背景颜色 | `...

(GL_BARBARISM_REPLACE)


[locale-violation] ~136-~136: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...| 24px | | --nutui-inputnumber-input-background-color | 数字输入框中input的背景颜色 | `$color-back...

(GL_BARBARISM_REPLACE)


[locale-violation] ~136-~136: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...t-background-color | 数字输入框中input的背景颜色 | $color-background | | --nutui-inputnumber-input-font-co...

(GL_BARBARISM_REPLACE)


[locale-violation] ~137-~137: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...or-background| | \--nutui-inputnumber-input-font-color | 数字输入框中input的字号颜色 |$color...

(GL_BARBARISM_REPLACE)


[locale-violation] ~138-~138: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...$color-title | | --nutui-inputnumber-input-font-size | 数字输入框中input的字号大小 | 14px |...

(GL_BARBARISM_REPLACE)


[locale-violation] ~139-~139: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...的字号大小 | 14px | | --nutui-inputnumber-input-border | 数字输入框中input的border值 | 0 | | ...

(GL_BARBARISM_REPLACE)


[locale-violation] ~140-~140: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...的border值 | 0 | | --nutui-inputnumber-input-border-radius | 数字输入框中input的圆角 | 6px ...

(GL_BARBARISM_REPLACE)


[locale-violation] ~141-~141: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...put的圆角 | 6px | | --nutui-inputnumber-input-margin | 数字输入框中input的margin值 | 0 | | ...

(GL_BARBARISM_REPLACE)

🪛 Biome (1.9.4)
src/packages/inputnumber/inputnumber.taro.tsx

[error] 209-209: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

src/packages/inputnumber/inputnumber.tsx

[error] 206-206: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🪛 GitHub Check: codecov/patch
src/packages/inputnumber/inputnumber.tsx

[warning] 191-191: src/packages/inputnumber/inputnumber.tsx#L191
Added line #L191 was not covered by tests

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: test
🔇 Additional comments (24)
src/packages/inputnumber/inputnumber.tsx (5)

12-12: 引入 bound 函数值得肯定。
它能有效限制数值范围,避免越界问题。


31-31: 新增 beforeChange 属性接口设计合理。
支持同步或异步布尔判断,为后续异步逻辑扩展提供良好基础。


48-48: 默认值使用 Promise.resolve(true) 合理。
确保在未显式传入 beforeChange 时也能正常运行,无需额外判断。


77-77: 在解构中获取 beforeChange
此处逻辑清晰,暂无明显问题。


106-110: 使用 bound 校正数值边界有助于稳定性。
同时要注意解析浮点数时可能出现非数字(NaN)的特殊情况,建议在后续调用链中确认。

src/packages/inputnumber/inputnumber.taro.tsx (8)

2-3: 导入类型声明合理。
ChangeEventFunctionComponent 有助于更好地约束函数入参。


9-10: 引入 classNames 库与 Taro 组件配合正常。
注意后续若引入更多第三方组件库时,避免冲突即可。


13-13: 使用 bound 函数防止数值越界。
同样需留意 NaN 的情况,减少潜在异常。


33-37: 扩展 onChange 增加对 React.MouseEvent 的兼容。
Taro 端操作时可能混合使用不同事件,兼容性值得肯定。


50-50: 默认 beforeChange 函数可减少调用方的额外判断。
与主项目逻辑保持一致。


80-80: 在解构 props 时引入 beforeChange
便于在下方统一管理异步逻辑,风格一致。


138-161: update 函数异步化后结构更清晰。
配合 beforeChange 能灵活控制是否更新值,易读易维护。


176-197: handleInputChange 实现异步校验,可满足复杂场景需求。
beforeChange 返回 false,逻辑能即时中断,操作体验更流畅。

src/packages/inputnumber/demos/h5/demo8.tsx (2)

2-2: 导入 Toast 并展示加载动画是个好想法。
能在演示场景更直观地反馈异步操作。


22-28: 修改 min-9999 并使用 beforeChange 优化示例逻辑。
支持更大数值范围,加上异步校验,能更好展示高级用法。

src/packages/inputnumber/demos/taro/demo8.tsx (1)

19-28: 异步处理逻辑优化良好

新增的 beforeChange 方法通过 Promise 实现了更优雅的异步处理,代替了原有的 async 属性。

src/packages/inputnumber/__tests__/inputnumber.spec.tsx (1)

12-33: 测试用例异步处理改进

使用 actasync/await 正确处理了异步操作,确保测试结果的准确性。

src/packages/inputnumber/doc.zh-TW.md (2)

116-119: 文档更新清晰完整

  • 正确标注了 async 属性的废弃
  • 新增了 beforeChangeselect 属性的说明

135-145: CSS 变量更新合理

样式变量的默认值调整提升了组件的视觉表现。

🧰 Tools
🪛 LanguageTool

[locale-violation] ~135-~135: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...-- | --- | --- | | --nutui-inputnumber-input-width | 數字輸入框中input的寬度 | 40px | | --...

(GL_BARBARISM_REPLACE)


[locale-violation] ~136-~136: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...ut的寬度 | 40px | | --nutui-inputnumber-input-height | 數字輸入框中input的高度 | 24px | | -...

(GL_BARBARISM_REPLACE)


[locale-violation] ~137-~137: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...ut的高度 | 24px | | --nutui-inputnumber-input-background-color | 數字輸入框中input的背景顏色 | `...

(GL_BARBARISM_REPLACE)


[locale-violation] ~137-~137: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...| 24px | | --nutui-inputnumber-input-background-color | 數字輸入框中input的背景顏色 | `$color-back...

(GL_BARBARISM_REPLACE)


[locale-violation] ~137-~137: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...t-background-color | 數字輸入框中input的背景顏色 | $color-background | | --nutui-inputnumber-input-font-co...

(GL_BARBARISM_REPLACE)


[locale-violation] ~138-~138: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...or-background| | \--nutui-inputnumber-input-font-color | 數字輸入框中input的字號顏色 |$color...

(GL_BARBARISM_REPLACE)


[locale-violation] ~139-~139: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...$color-title | | --nutui-inputnumber-input-font-size | 數字輸入框中input的字號大小 | 14px |...

(GL_BARBARISM_REPLACE)


[locale-violation] ~140-~140: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...的字號大小 | 14px | | --nutui-inputnumber-input-border | 數字輸入框中input的border值 | 0 | | ...

(GL_BARBARISM_REPLACE)


[locale-violation] ~141-~141: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...的border值 | 0 | | --nutui-inputnumber-input-border-radius | 數字輸入框中input的圓角 | 6px ...

(GL_BARBARISM_REPLACE)


[locale-violation] ~142-~142: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...put的圓角 | 6px | | --nutui-inputnumber-input-margin | 數字輸入框中input的margin值 | 0 | | ...

(GL_BARBARISM_REPLACE)

src/packages/inputnumber/doc.taro.md (2)

118-122: 事件类型更新准确

更新后的事件类型更好地支持了移动端触摸事件。


134-144: 样式变量更新合理

新的尺寸和圆角设置提升了移动端的用户体验。

🧰 Tools
🪛 LanguageTool

[locale-violation] ~134-~134: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...-- | --- | --- | | --nutui-inputnumber-input-width | 数字输入框中input的宽度 | 40px | | --...

(GL_BARBARISM_REPLACE)


[locale-violation] ~135-~135: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...ut的宽度 | 40px | | --nutui-inputnumber-input-height | 数字输入框中input的高度 | 24px | | -...

(GL_BARBARISM_REPLACE)


[locale-violation] ~136-~136: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...ut的高度 | 24px | | --nutui-inputnumber-input-background-color | 数字输入框中input的背景颜色 | `...

(GL_BARBARISM_REPLACE)


[locale-violation] ~136-~136: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...| 24px | | --nutui-inputnumber-input-background-color | 数字输入框中input的背景颜色 | `$color-back...

(GL_BARBARISM_REPLACE)


[locale-violation] ~136-~136: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...t-background-color | 数字输入框中input的背景颜色 | $color-background | | --nutui-inputnumber-input-font-co...

(GL_BARBARISM_REPLACE)


[locale-violation] ~137-~137: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...or-background| | \--nutui-inputnumber-input-font-color | 数字输入框中input的字号颜色 |$color...

(GL_BARBARISM_REPLACE)


[locale-violation] ~138-~138: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...$color-title | | --nutui-inputnumber-input-font-size | 数字输入框中input的字号大小 | 14px |...

(GL_BARBARISM_REPLACE)


[locale-violation] ~139-~139: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...的字号大小 | 14px | | --nutui-inputnumber-input-border | 数字输入框中input的border值 | 0 | | ...

(GL_BARBARISM_REPLACE)


[locale-violation] ~140-~140: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...的border值 | 0 | | --nutui-inputnumber-input-border-radius | 数字输入框中input的圆角 | 6px ...

(GL_BARBARISM_REPLACE)


[locale-violation] ~141-~141: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...put的圆角 | 6px | | --nutui-inputnumber-input-margin | 数字输入框中input的margin值 | 0 | | ...

(GL_BARBARISM_REPLACE)

src/packages/inputnumber/doc.md (1)

124-127: 属性描述更新正确
本次更新将废弃的 async 属性标记并添加了 beforeChange 属性,同时附带了版本提示。文档中针对异步修改的描述清晰,符合新版实现逻辑,建议开发者确认文档描述与组件代码的一致性。

src/packages/inputnumber/doc.en-US.md (2)

124-127: Property Description Update Verified
The deprecation of the async property and the introduction of the beforeChange property—with appropriate version notes—are clearly documented. Ensure that the description remains consistent with the underlying component implementation.


143-153: CSS Variable Updates Confirmed
The changes in CSS variable default values and the addition of the new variable --nutui-inputnumber-button-border-radius align with the component’s updated design. Please verify that these values match the design specifications.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (5)
src/packages/inputnumber/doc.md (2)

126-126: 建议改善属性描述格式。
在新增的 beforeChange 属性这一行中,建议将属性名称与版本信息分开显示,例如使用 `beforeChange` (2.8.0) 的格式,这样可使信息更清晰、一致。


142-152: 建议调整描述中的用词。
在 CSS 变量部分,文档描述中出现了 “input” 这一外来词。建议将 “input” 替换为更符合中文表达习惯的词汇,如 “输入框” 或 “输入区域”,以提升文档的本地化质量。

🧰 Tools
🪛 LanguageTool

[locale-violation] ~142-~142: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...-- | --- | --- | | --nutui-inputnumber-input-width | 数字输入框中input的宽度 | 40px | | --...

(GL_BARBARISM_REPLACE)


[locale-violation] ~143-~143: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...ut的宽度 | 40px | | --nutui-inputnumber-input-height | 数字输入框中input的高度 | 24px | | -...

(GL_BARBARISM_REPLACE)


[locale-violation] ~144-~144: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...ut的高度 | 24px | | --nutui-inputnumber-input-background-color | 数字输入框中input的背景颜色 | `...

(GL_BARBARISM_REPLACE)


[locale-violation] ~144-~144: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...| 24px | | --nutui-inputnumber-input-background-color | 数字输入框中input的背景颜色 | `$color-back...

(GL_BARBARISM_REPLACE)


[locale-violation] ~144-~144: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...t-background-color | 数字输入框中input的背景颜色 | $color-background | | --nutui-inputnumber-input-font-co...

(GL_BARBARISM_REPLACE)


[locale-violation] ~145-~145: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...or-background| | \--nutui-inputnumber-input-font-color | 数字输入框中input的字号颜色 |$color...

(GL_BARBARISM_REPLACE)


[locale-violation] ~146-~146: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...$color-title | | --nutui-inputnumber-input-font-size | 数字输入框中input的字号大小 | 14px |...

(GL_BARBARISM_REPLACE)


[locale-violation] ~147-~147: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...的字号大小 | 14px | | --nutui-inputnumber-input-border | 数字输入框中input的border值 | 0 | | ...

(GL_BARBARISM_REPLACE)


[locale-violation] ~148-~148: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...的border值 | 0 | | --nutui-inputnumber-input-border-radius | 数字输入框中input的圆角 | 6px ...

(GL_BARBARISM_REPLACE)


[locale-violation] ~149-~149: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...put的圆角 | 6px | | --nutui-inputnumber-input-margin | 数字输入框中input的margin值 | 0 | | ...

(GL_BARBARISM_REPLACE)

src/packages/inputnumber/doc.zh-TW.md (2)

118-118: 建议格式化与文字统一。
对于新增的 beforeChange 属性,建议将属性名称与版本信息分开显示(例如:`beforeChange` (2.8.0)),同时将描述中的 “输入值” 修改为繁体 “輸入值”,以保持语言风格的一致性。


134-144: 建议调整描述用词。
CSS 变量部分的描述中使用了 “input” 一词,建议替换为更合适的繁体中文表达,例如 “輸入框”,从而提升描述的本地化准确性。

🧰 Tools
🪛 LanguageTool

[locale-violation] ~134-~134: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...-- | --- | --- | | --nutui-inputnumber-input-width | 數字輸入框中input的寬度 | 40px | | --...

(GL_BARBARISM_REPLACE)


[locale-violation] ~135-~135: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...ut的寬度 | 40px | | --nutui-inputnumber-input-height | 數字輸入框中input的高度 | 24px | | -...

(GL_BARBARISM_REPLACE)


[locale-violation] ~136-~136: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...ut的高度 | 24px | | --nutui-inputnumber-input-background-color | 數字輸入框中input的背景顏色 | `...

(GL_BARBARISM_REPLACE)


[locale-violation] ~136-~136: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...| 24px | | --nutui-inputnumber-input-background-color | 數字輸入框中input的背景顏色 | `$color-back...

(GL_BARBARISM_REPLACE)


[locale-violation] ~136-~136: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...t-background-color | 數字輸入框中input的背景顏色 | $color-background | | --nutui-inputnumber-input-font-co...

(GL_BARBARISM_REPLACE)


[locale-violation] ~137-~137: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...or-background| | \--nutui-inputnumber-input-font-color | 數字輸入框中input的字號顏色 |$color...

(GL_BARBARISM_REPLACE)


[locale-violation] ~138-~138: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...$color-title | | --nutui-inputnumber-input-font-size | 數字輸入框中input的字號大小 | 14px |...

(GL_BARBARISM_REPLACE)


[locale-violation] ~139-~139: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...的字號大小 | 14px | | --nutui-inputnumber-input-border | 數字輸入框中input的border值 | 0 | | ...

(GL_BARBARISM_REPLACE)


[locale-violation] ~140-~140: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...的border值 | 0 | | --nutui-inputnumber-input-border-radius | 數字輸入框中input的圓角 | 6px ...

(GL_BARBARISM_REPLACE)


[locale-violation] ~141-~141: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...put的圓角 | 6px | | --nutui-inputnumber-input-margin | 數字輸入框中input的margin值 | 0 | | ...

(GL_BARBARISM_REPLACE)

src/packages/inputnumber/doc.en-US.md (1)

126-126: Improve property format clarity.
对于新增的 beforeChange 属性,建议将属性名称与版本信息分开,例如:`beforeChange` (2.8.0),以确保文档格式的一致性和可读性.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between adf3f0f and 51451b7.

📒 Files selected for processing (3)
  • src/packages/inputnumber/doc.en-US.md (2 hunks)
  • src/packages/inputnumber/doc.md (2 hunks)
  • src/packages/inputnumber/doc.zh-TW.md (2 hunks)
🧰 Additional context used
🪛 LanguageTool
src/packages/inputnumber/doc.md

[locale-violation] ~142-~142: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...-- | --- | --- | | --nutui-inputnumber-input-width | 数字输入框中input的宽度 | 40px | | --...

(GL_BARBARISM_REPLACE)


[locale-violation] ~143-~143: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...ut的宽度 | 40px | | --nutui-inputnumber-input-height | 数字输入框中input的高度 | 24px | | -...

(GL_BARBARISM_REPLACE)


[locale-violation] ~144-~144: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...ut的高度 | 24px | | --nutui-inputnumber-input-background-color | 数字输入框中input的背景颜色 | `...

(GL_BARBARISM_REPLACE)


[locale-violation] ~144-~144: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...| 24px | | --nutui-inputnumber-input-background-color | 数字输入框中input的背景颜色 | `$color-back...

(GL_BARBARISM_REPLACE)


[locale-violation] ~144-~144: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...t-background-color | 数字输入框中input的背景颜色 | $color-background | | --nutui-inputnumber-input-font-co...

(GL_BARBARISM_REPLACE)


[locale-violation] ~145-~145: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...or-background| | \--nutui-inputnumber-input-font-color | 数字输入框中input的字号颜色 |$color...

(GL_BARBARISM_REPLACE)


[locale-violation] ~146-~146: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...$color-title | | --nutui-inputnumber-input-font-size | 数字输入框中input的字号大小 | 14px |...

(GL_BARBARISM_REPLACE)


[locale-violation] ~147-~147: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...的字号大小 | 14px | | --nutui-inputnumber-input-border | 数字输入框中input的border值 | 0 | | ...

(GL_BARBARISM_REPLACE)


[locale-violation] ~148-~148: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...的border值 | 0 | | --nutui-inputnumber-input-border-radius | 数字输入框中input的圆角 | 6px ...

(GL_BARBARISM_REPLACE)


[locale-violation] ~149-~149: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...put的圆角 | 6px | | --nutui-inputnumber-input-margin | 数字输入框中input的margin值 | 0 | | ...

(GL_BARBARISM_REPLACE)

src/packages/inputnumber/doc.zh-TW.md

[locale-violation] ~134-~134: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...-- | --- | --- | | --nutui-inputnumber-input-width | 數字輸入框中input的寬度 | 40px | | --...

(GL_BARBARISM_REPLACE)


[locale-violation] ~135-~135: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...ut的寬度 | 40px | | --nutui-inputnumber-input-height | 數字輸入框中input的高度 | 24px | | -...

(GL_BARBARISM_REPLACE)


[locale-violation] ~136-~136: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...ut的高度 | 24px | | --nutui-inputnumber-input-background-color | 數字輸入框中input的背景顏色 | `...

(GL_BARBARISM_REPLACE)


[locale-violation] ~136-~136: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...| 24px | | --nutui-inputnumber-input-background-color | 數字輸入框中input的背景顏色 | `$color-back...

(GL_BARBARISM_REPLACE)


[locale-violation] ~136-~136: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...t-background-color | 數字輸入框中input的背景顏色 | $color-background | | --nutui-inputnumber-input-font-co...

(GL_BARBARISM_REPLACE)


[locale-violation] ~137-~137: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...or-background| | \--nutui-inputnumber-input-font-color | 數字輸入框中input的字號顏色 |$color...

(GL_BARBARISM_REPLACE)


[locale-violation] ~138-~138: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...$color-title | | --nutui-inputnumber-input-font-size | 數字輸入框中input的字號大小 | 14px |...

(GL_BARBARISM_REPLACE)


[locale-violation] ~139-~139: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...的字號大小 | 14px | | --nutui-inputnumber-input-border | 數字輸入框中input的border值 | 0 | | ...

(GL_BARBARISM_REPLACE)


[locale-violation] ~140-~140: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...的border值 | 0 | | --nutui-inputnumber-input-border-radius | 數字輸入框中input的圓角 | 6px ...

(GL_BARBARISM_REPLACE)


[locale-violation] ~141-~141: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...put的圓角 | 6px | | --nutui-inputnumber-input-margin | 數字輸入框中input的margin值 | 0 | | ...

(GL_BARBARISM_REPLACE)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: test
🔇 Additional comments (3)
src/packages/inputnumber/doc.zh-TW.md (1)

116-116: 新增属性 select 验证。
属性 select 已成功新增,说明文本与默认值均符合预期。

src/packages/inputnumber/doc.en-US.md (2)

124-124: New property select verified.
新增的 select 属性已正确添加,说明信息清晰且符合预期。


142-152: CSS variable updates confirmed.
英文文档中对 CSS 变量的更新描述与最新改动保持一致,整体表述清晰。

@xiaoyatong
Copy link
Collaborator

设置min和max时,超过范围后,点击+ 或 -,数据异常
image

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (5)
src/packages/inputnumber/inputnumber.taro.tsx (3)

138-161: 异步更新逻辑实现

update 函数改为异步并加入了 beforeChange 验证,这很好地解决了异步验证的需求。但注意一点:在检查边界值之前应用 beforeChange 可能导致边界条件处理不一致。

建议考虑在验证过程中保持一致的边界条件检查逻辑。

 const update = async (negative: boolean, e: ITouchEvent) => {
   if (step === undefined) return
   negative ? onMinus?.(e) : onPlus?.(e)

   const shouldOverBoundary = calcNextValue(
     bound(Number(shadowValue), Number(min), Number(max)),
     step,
     negative ? -1 : 1
   )
+  // 在检查边界前先确保值在合理范围内
+  const boundedValue = bound(shouldOverBoundary, Number(min), Number(max))
-  const maybeResume = await beforeChange(Number(shouldOverBoundary))
+  const maybeResume = await beforeChange(Number(boundedValue))
   if (!maybeResume) return

-  const nextValue = bound(shouldOverBoundary, Number(min), Number(max))
+  const nextValue = boundedValue
   setShadowValue(nextValue)
   if (
     negative
       ? shouldOverBoundary < Number(min)
       : shouldOverBoundary > Number(max)
   ) {
     onOverlimit?.(e)
   } else {
     onChange?.(nextValue, e)
   }
 }

176-196: 输入变更的异步处理实现

handleInputChange 函数现在正确地等待 beforeChange 的结果,并根据结果决定是否继续。这增强了组件的可控性。

有一个小问题:在调用 beforeChange 时直接使用 Number(valueStr) 可能将 null 转为 0,这可能不是期望的行为。

 const handleInputChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
   // 设置 input 值, 在 blur 时格式化
   setInputValue(e.target.value)
   const valueStr = parseValue(e.target.value)
-  const maybeResume = await beforeChange(Number(valueStr))
+  // 对 null 值的处理更加明确
+  const maybeResume = await beforeChange(valueStr === null ? (allowEmpty ? null : defaultValue) : Number(valueStr))
   if (!maybeResume) return

   setShadowValue(
     // eslint-disable-next-line no-nested-ternary
     valueStr === null ? (allowEmpty ? null : defaultValue) : valueStr
   )

206-211: 失焦处理的改进

handleBlur 函数的改进使用可选链调用 onBlur,并直接调用 onChange 确保值更新,这是符合预期的行为。

不过这里可以使用可选链运算符来简化代码:

- onBlur && onBlur(e)
+ onBlur?.(e)
🧰 Tools
🪛 Biome (1.9.4)

[error] 209-209: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

src/packages/inputnumber/inputnumber.tsx (2)

135-157: 异步更新逻辑实现

update 函数改为异步并加入了 beforeChange 验证,这很好地解决了异步验证的需求。不过这里存在与 Taro 版本相同的问题。

建议考虑在验证过程中保持一致的边界条件检查逻辑,确保传入 beforeChange 的值是经过边界处理的。

 const update = async (negative: boolean, e: React.MouseEvent) => {
   if (step === undefined) return
   negative ? onMinus?.(e) : onPlus?.(e)

   const shouldOverBoundary = calcNextValue(
     bound(Number(shadowValue), Number(min), Number(max)),
     step,
     negative ? -1 : 1
   )
+  // 在检查边界前先确保值在合理范围内
+  const boundedValue = bound(shouldOverBoundary, Number(min), Number(max))
-  const maybeResume = await beforeChange(Number(shouldOverBoundary))
+  const maybeResume = await beforeChange(Number(boundedValue))
   if (!maybeResume) return

-  const nextValue = bound(shouldOverBoundary, Number(min), Number(max))
+  const nextValue = boundedValue
   setShadowValue(nextValue)

205-207: 失焦处理的改进

handleBlur 函数的改进,但同样可以使用可选链运算符来简化代码:

- onBlur && onBlur(e)
+ onBlur?.(e)
🧰 Tools
🪛 Biome (1.9.4)

[error] 206-206: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 51451b7 and fc7c7fa.

📒 Files selected for processing (2)
  • src/packages/inputnumber/inputnumber.taro.tsx (8 hunks)
  • src/packages/inputnumber/inputnumber.tsx (7 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
src/packages/inputnumber/inputnumber.taro.tsx

[error] 209-209: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

src/packages/inputnumber/inputnumber.tsx

[error] 206-206: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🪛 GitHub Check: codecov/patch
src/packages/inputnumber/inputnumber.tsx

[warning] 191-191: src/packages/inputnumber/inputnumber.tsx#L191
Added line #L191 was not covered by tests

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: test
🔇 Additional comments (13)
src/packages/inputnumber/inputnumber.taro.tsx (8)

33-33: 引入 beforeChange 属性增强组件的可控性

通过添加 beforeChange 钩子函数,使开发者可以在值变化前进行拦截,非常适合需要异步验证的场景。这是一个很好的改进,增强了组件的灵活性。


36-36: 事件类型扩展正确

扩展 onChange 的事件类型支持 React.MouseEvent,这使得组件在不同触发方式下都能正确传递事件对象。


50-50: 默认属性实现良好

beforeChange 提供了一个默认实现,返回 Promise.resolve(true),确保在未提供该属性时组件仍能正常工作。


85-88: 类名处理简化

使用 classNames 库简化了类名的条件添加,提高了代码可读性。


106-113: 格式化函数改进

format 函数的改进确保了在应用边界值限制前正确解析字符串值,这是一个很好的纠正。


131-136: 计算下一个值的逻辑优化

calcNextValue 函数通过正确处理浮点数计算,避免了精度问题,实现得很好。


162-165: 减少和增加按钮处理程序更新

handleReducehandlePlus 函数更新为异步并等待 update 完成,这是正确的改动,确保了异步操作的顺序执行。

Also applies to: 166-169


217-221: 图标样式的优化

使用 classNames 简化了条件类名的添加,提高了代码可读性。

Also applies to: 242-246

src/packages/inputnumber/inputnumber.tsx (5)

31-31: 引入 beforeChange 属性增强组件的可控性

通过添加 beforeChange 钩子函数,使开发者可以在值变化前进行拦截,非常适合需要异步验证的场景。


48-48: 默认属性实现良好

beforeChange 提供了一个默认实现,返回 Promise.resolve(true),确保在未提供该属性时组件仍能正常工作。


106-110: 格式化函数改进

format 函数的改进确保了在应用边界值限制前正确解析字符串值,这是一个很好的纠正。


128-133: 计算下一个值的逻辑优化

calcNextValue 函数通过正确处理浮点数计算,避免了精度问题,实现得很好。


159-162: 减少和增加按钮处理程序更新

handleReducehandlePlus 函数更新为异步并等待 update 完成,这是正确的改动,确保了异步操作的顺序执行。

Also applies to: 163-166

Comment on lines +173 to 192
const handleInputChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
// 设置 input 值, 在 blur 时格式化
setInputValue(e.target.value)
const valueStr = parseValue(e.target.value)
if (valueStr === null) {
if (allowEmpty) {
setShadowValue(null)
} else {
setShadowValue(defaultValue)
}
const maybeResume = await beforeChange(Number(valueStr))
if (!maybeResume) return

setShadowValue(
// eslint-disable-next-line no-nested-ternary
valueStr === null ? (allowEmpty ? null : defaultValue) : valueStr
)

if (
valueStr !== null &&
(Number(valueStr) < Number(min) || Number(valueStr) > Number(max))
) {
onOverlimit?.(e)
} else {
setShadowValue(clampValue(valueStr) as any)
onChange?.(parseFloat(valueStr || '0').toFixed(digits), e)
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

输入变更的异步处理实现

handleInputChange 函数现在正确地等待 beforeChange 的结果,并根据结果决定是否继续。

代码覆盖检查工具显示第191行未被测试覆盖。建议添加相应的测试用例,确保这部分逻辑正确工作。

建议添加以下测试场景:

  1. 测试当输入值小于最小值时 onOverlimit 被调用
  2. 测试当输入值大于最大值时 onOverlimit 被调用
  3. 测试当 beforeChange 返回 false 时,值不更新

🌐 Web query:

什么是常见的 React 组件测试模式?

💡 Result:

常见的 React 组件测试模式可分为以下几类,主要围绕用户交互、状态管理和异步操作展开:

1. 渲染与内容验证

  • 快照测试:捕获组件渲染的 DOM 结构,快速检测 UI 变化是否合理。
    test('input snapshot', () => {
      const { container } = render(<Input />);
      expect(container.firstChild).toMatchSnapshot();
    });
  • DOM 元素断言:通过文本、属性或角色验证元素是否存在。
    render(<Note content="测试内容" />);
    expect(screen.getByText('测试内容')).toBeInTheDocument();

2. 用户交互模拟

  • 事件触发与响应:模拟点击、输入等操作,验证组件状态或 UI 变化。
    const button = screen.getByTestId('toggle-button');
    await user.click(button);
    expect(screen.getByText('Turn off')).toBeVisible();
  • 表单测试:模拟用户填写表单并提交,验证提交逻辑和结果。
    fireEvent.change(input, { target: { value: '新内容' } });
    fireEvent.click(submitButton);
    await waitFor(() => expect(mockSubmit).toHaveBeenCalledWith('新内容'));

3. 异步与 API 测试

  • Mock 网络请求:拦截 API 调用并返回预设数据。
    jest.spyOn(global, 'fetch').mockResolvedValue({ json: () => mockData });
    render(<UserList />);
    await waitFor(() => expect(screen.getAllByRole('listitem')).toHaveLength(2));
  • 定时器控制:使用 Jest 假定时器测试延迟操作(如加载状态)。
    jest.useFakeTimers();
    render(<Loader />);
    act(() => jest.runAllTimers());
    expect(screen.queryByText('Loading...')).toBeNull();

4. 状态与 Props 管理

  • Props 变化响应:测试组件对 props 更新的处理。
    const { rerender } = render(<Counter initial={0} />);
    rerender(<Counter initial={5} />);
    expect(screen.getByText('5')).toBeInTheDocument();
  • 状态更新验证:通过交互触发状态变化,验证 UI 同步更新。
    fireEvent.click(incrementButton);
    expect(screen.getByTestId('count')).toHaveTextContent('1');

5. 集成与上下文测试

  • Redux 或 Context 集成:包裹组件于 Provider 中,测试状态管理逻辑。
    const store = configureStore({ reducer: { data: mockReducer } });
    render(<Provider store={store}><ConnectedComponent /></Provider>);
    expect(screen.getByText('Data loaded')).toBeVisible();
  • 路由测试:模拟导航并验证组件渲染。
    const history = createMemoryHistory();
    render(<Router history={history}><RouteComponent /></Router>);
    act(() => history.push('/details'));
    expect(screen.getByText('详情页')).toBeInTheDocument();

6. Mock 与依赖隔离

  • 子组件 Mock:简化复杂子组件的测试。
    jest.mock('./ChildComponent', () => () => <div data-testid="mock-child" />);
    render(<ParentComponent />);
    expect(screen.getByTestId('mock-child')).toBeInTheDocument();
  • 函数调用验证:检查回调是否被正确触发。
    const mockOnSubmit = jest.fn();
    render(<Form onSubmit={mockOnSubmit} />);
    fireEvent.submit(form);
    expect(mockOnSubmit).toHaveBeenCalledTimes(1);

工具推荐

  • Jest:用于测试运行、断言和模拟(如函数、模块)。
  • React Testing Library:以用户视角测试组件,避免依赖内部实现。
  • MSW (Mock Service Worker):拦截 API 请求,提供更真实的网络模拟。
  • Enzyme (旧项目):允许浅渲染和直接状态访问,适合复杂组件内部测试。

通过结合这些模式,可确保 React 组件在不同场景下的功能正确性,同时提升测试的可维护性和执行效率[1][4][6][11]。

Citations:


完善异步输入处理的测试用例

目前 handleInputChange 函数已正确等待 beforeChange 的返回结果,并根据该结果执行后续逻辑。不过代码覆盖率工具提示第191行未被覆盖,建议补充单元测试,确保以下场景能被充分验证:

  • 当输入值小于最小值或大于最大值时,应调用 onOverlimit 回调;
  • beforeChange 返回 false 时,不应更新状态,也不应调用 onChange 回调。

建议采用常见的 React 组件测试模式,如使用 Jest 和 React Testing Library 的快照测试、用户事件模拟和异步操作验证,来构建并覆盖这一逻辑。请根据这些测试模式完善单元测试,确保组件在各种输入条件下的行为均正确。

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 191-191: src/packages/inputnumber/inputnumber.tsx#L191
Added line #L191 was not covered by tests

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
src/packages/inputnumber/demos/h5/demo8.tsx (1)

9-19: 添加 beforeChange 为组件增加了异步验证能力

beforeChange 函数的实现允许在实际更改值之前进行异步验证。返回 Promise 并在 500ms 后解析,这种模式能够支持更复杂的验证场景,如服务器验证或复杂计算。

建议考虑添加错误处理逻辑:

const beforeChange = (value: number | string): Promise<boolean> => {
  Toast.show({ icon: 'loading', content: '异步演示2秒后更改' })

  return new Promise((resolve) => {
    setTimeout(() => {
      Toast.clear()
      resolve(true)
+     // 可以根据条件返回 false 以阻止更改
+     // 或添加 try/catch 处理可能的异常
    }, 500)
  })
}
src/packages/inputnumber/demos/taro/demo8.tsx (2)

6-8: 状态设置函数命名规范化

SetShowSetToastMsgSetToastType 更正为小写开头的 setShowsetToastMsgsetToastType,符合 React 命名规范。

这是一个很好的改进,统一使用小驼峰命名法可以提高代码一致性。


18-28: 实现 beforeChange 函数

添加了与 H5 版本相同的 beforeChange 功能,提供了异步验证能力。此函数显示加载提示,并在 500ms 后允许值更改。

建议考虑拓展功能,让用户可以根据验证结果决定是否允许更改:

const beforeChange = (value: number | string): Promise<boolean> => {
  toastShow('异步演示 2 秒后更改', 'loading')

  return new Promise((resolve) => {
    setTimeout(() => {
      setShow(false)
-     resolve(true)
+     // 可以基于条件返回不同结果
+     const isValid = Number(value) <= 10000 // 示例验证
+     if (!isValid) {
+       toastShow('数值过大', 'text')
+     }
+     resolve(isValid)
    }, 500)
  })
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fc7c7fa and 26288e6.

📒 Files selected for processing (2)
  • src/packages/inputnumber/demos/h5/demo8.tsx (1 hunks)
  • src/packages/inputnumber/demos/taro/demo8.tsx (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: test
  • GitHub Check: build
🔇 Additional comments (4)
src/packages/inputnumber/demos/h5/demo8.tsx (1)

25-27: min 值修改和 beforeChange 的集成

扩大了数值输入范围并集成了新的 beforeChange 功能,同时保留了正常的 onChange 处理。这种组合能够更好地处理用户输入验证流程。

请验证当用户点击按钮超出限制时,是否正确触发 onOverlimit 事件并且不会出现 PR 评论中提到的数据异常情况。

src/packages/inputnumber/demos/taro/demo8.tsx (3)

11-13: 使用更正后的状态设置函数

更新函数调用以使用重命名后的状态设置函数。这确保了代码的一致性。


33-39: InputNumber 组件属性更新

  1. 将 min 值从 -6 扩展到 -9999,大幅扩展了可输入范围
  2. 添加了 beforeChange 处理
  3. 保留了 onChange 处理用于状态更新
  4. 添加了 onOverlimit 回调以处理超出限制情况

这些更改全面优化了组件的交互逻辑。

请确保组件能够正确处理用户尝试输入超出范围值时的情况,特别是针对 PR 评论中提到的问题,当用户点击超出限制的 +/- 按钮时不应出现数据异常。


46-46: 使用更正后的状态设置函数

更新使用重命名后的 setShow 函数。

# Conflicts:
#	src/packages/inputnumber/inputnumber.taro.tsx
#	src/packages/inputnumber/inputnumber.tsx
@oasis-cloud
Copy link
Collaborator Author

设置min和max时,超过范围后,点击+ 或 -,数据异常 image

fixed

# Conflicts:
#	src/sites/sites-react/doc/docs/react/migrate-from-v2.en-US.md
#	src/sites/sites-react/doc/docs/taro/migrate-from-v2.en-US.md
#	src/sites/sites-react/doc/docs/taro/migrate-from-v2.md
@xiaoyatong xiaoyatong merged commit 3a94dfe into jdf2e:feat_v3.x Mar 12, 2025
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

3.x Target branch 3.x action:review This PR needs more reviews (less than 2 approvals) size/XL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants