Skip to content

feat(searchbar): v15 适配,增加了受控和默认值#3209

Merged
oasis-cloud merged 15 commits intojdf2e:feat_v3.xfrom
xiaoyatong:feat3/searchbar
May 15, 2025
Merged

feat(searchbar): v15 适配,增加了受控和默认值#3209
oasis-cloud merged 15 commits intojdf2e:feat_v3.xfrom
xiaoyatong:feat3/searchbar

Conversation

@xiaoyatong
Copy link
Collaborator

@xiaoyatong xiaoyatong commented Apr 28, 2025

🤔 这个变动的性质是?

  • 新特性提交
  • 日常 bug 修复
  • 站点、文档改进
  • 演示代码改进
  • 组件样式/交互改进
  • TypeScript 定义更新
  • 包体积优化
  • 性能优化
  • 功能增强
  • 国际化改进
  • 重构
  • 代码风格优化
  • 测试用例
  • 分支合并
  • 其他改动(是关于什么的改动?)

🔗 相关 Issue

💡 需求背景和解决方案

☑️ 请求合并前的自查清单

⚠️ 请自检并全部勾选全部选项⚠️

  • 文档已补充或无须补充
  • 代码演示已提供或无须提供
  • TypeScript 定义已补充或无须补充
  • fork仓库代码是否为最新避免文件冲突
  • Files changed 没有 package.json lock 等无关文件

Summary by CodeRabbit

  • 新功能

    • SearchBar 组件新增支持 defaultValue 属性,可设置多个默认值(以逗号分隔),并支持 onItemClick 回调处理默认值的点击事件。
    • 默认值支持点击“x”按钮移除,提升交互体验。
    • 新增多个演示示例,展示 defaultValue 与受控模式的使用。
  • 样式

    • SearchBar 组件样式优化:调整内外边距、背景色、圆角、输入框高度与图标尺寸,默认主题更美观。
    • 默认值展示区域及相关图标样式增强。
  • 文档

    • 更新 SearchBar 相关文档,详细说明 defaultValueonItemClick 新增属性及样式变量变更,完善 API 说明及迁移指引。
  • 演示/示例

    • 新增和优化 SearchBar 组件的多个演示用例,展示不同配置及交互效果。
  • 测试

    • 扩展并重构 SearchBar 组件测试,新增对默认值渲染、右侧元素及事件处理的覆盖,提升测试完整性和准确性。

@coderabbitai
Copy link

coderabbitai bot commented Apr 28, 2025

## Walkthrough

本次更新对 SearchBar 组件进行了功能增强和样式优化。核心变更包括:引入了 `defaultValue` 属性支持多个默认值展示,并通过 `onItemClick` 回调处理默认值的删除操作;组件内部状态管理由 `useState` 切换为 `usePropsValue`,提升受控与非受控场景的兼容性。样式方面,调整了边距、背景色、圆角、icon 尺寸等变量,丰富了默认值展示的样式。文档和演示用例同步更新,增加了新特性说明与示例,类型定义也相应扩展。

## Changes

| 文件/路径分组                                                                 | 变更摘要                                                                                                  |
|-------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------|
| src/packages/searchbar/searchbar.tsx<br>src/packages/searchbar/searchbar.taro.tsx<br>src/types/spec/searchbar/base.ts | SearchBar 组件支持 `defaultValue` 和 `onItemClick`,内部状态管理重构为 `usePropsValue`,支持默认值点击删除,事件命名规范化,输入框 ref 重命名,右侧内容渲染优化。 |
| src/packages/searchbar/searchbar.scss<br>src/styles/variables.scss<br>src/styles/variables-jmapp.scss<br>src/styles/variables-jrkf.scss | 优化样式变量:边距、背景、圆角、icon 尺寸、输入框高度、游标颜色等,新增默认值展示样式,调整输入框及图标布局,移除并新增部分 SCSS 变量。            |
| src/packages/searchbar/demo.tsx<br>src/packages/searchbar/demo.taro.tsx<br>src/packages/searchbar/demos/h5/demo10.tsx<br>src/packages/searchbar/demos/taro/demo10.tsx | 新增默认值/受控用例 Demo10,演示 `defaultValue`、`onItemClick` 用法,调整 demo 展示顺序,新增对应多语言翻译,移除 `id-ID` 本地化。 |
| src/packages/searchbar/demos/h5/demo1.tsx<br>src/packages/searchbar/demos/taro/demo1.tsx | 优化 demo 用例:替换单一 SearchBar 为两个变体,丰富右侧内容及图标交互,调整图标导入路径。                          |
| src/packages/searchbar/demos/h5/demo3.tsx<br>src/packages/searchbar/demos/h5/demo5.tsx<br>src/packages/searchbar/demos/h5/demo2.tsx<br>src/packages/searchbar/demos/h5/demo4.tsx<br>src/packages/searchbar/demos/h5/demo6.tsx<br>src/packages/searchbar/demos/h5/demo7.tsx | 统一组件导入路径为 `@nutui/nutui-react`,移除部分图标尺寸限制,调整主题色和背景色,组件标签名调整。                    |
| src/packages/searchbar/doc.md<br>src/packages/searchbar/doc.taro.md<br>src/packages/searchbar/doc.zh-TW.md<br>src/packages/searchbar/doc.en-US.md | 文档补充 `defaultValue`、`onItemClick` 属性说明,更新 API、样式变量默认值,新增示例章节,修正部分描述和图标默认值。          |
| src/sites/sites-react/doc/docs/react/migrate-from-v2.md<br>src/sites/sites-react/doc/docs/taro/migrate-from-v2.md | 迁移文档补充新 API 说明,明确受控/非受控用法及默认值删除回调。                                               |
| src/packages/configprovider/types.ts                                          | 修改 `NutCSSVariables` 类型,新增 `nutuiSearchbarInnerGap` 和 `nutuiSearchbarIconSize`,移除 `nutuiSearchbarContentPadding`。 |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant 用户
    participant SearchBar
    participant 父组件

    用户->>SearchBar: 输入内容/点击默认值的“x”
    SearchBar->>SearchBar: 处理 value/defaultValue 状态
    alt 受控模式
        SearchBar->>父组件: onChange/onItemClick 回调
        父组件->>SearchBar: 更新 value/defaultValue
    else 非受控模式
        SearchBar->>SearchBar: 内部更新 value/defaultValue
    end
    SearchBar-->>用户: 渲染最新输入或默认值

Suggested reviewers

  • oasis-cloud
  • irisSong

Poem

小兔挥笔写新篇,
搜索栏里功能添。
默认值点一点,
“x”号轻松删;
样式变量焕新颜,
文档 demo 齐更新。
跳跃代码草丛间,
体验升级乐无边!

((\
( -.-)
o_(")(")


<!-- walkthrough_end -->
<!-- internal state start -->


<!-- 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 -->

<!-- internal state end -->
<!-- finishing_touch_checkbox_start -->

<details open="true">
<summary>✨ Finishing Touches</summary>

- [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> 📝 Generate Docstrings

</details>

<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->

---

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=jdf2e/nutui-react&utm_content=3209):

- 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.`

### Support

Need help? Create a ticket on our [support page](https://www.coderabbit.ai/contact-us/support) for assistance with any issues or questions.

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](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai generate sequence diagram` to generate a sequence diagram of the changes in 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](https://docs.coderabbit.ai/guides/configure-coderabbit) 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](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->

@github-actions github-actions bot added action:review This PR needs more reviews (less than 2 approvals) 3.x Target branch 3.x labels Apr 28, 2025
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: 2

🔭 Outside diff range comments (1)
src/packages/searchbar/searchbar.tsx (1)

178-193: ⚠️ Potential issue

clearaValonChange 参数缺失导致类型与语义不一致
onChange 约定签名为 (value: string, event: ChangeEvent<HTMLInputElement>)
但这里仅传入了字符串,可能触发 TS 警告甚至上层逻辑错误。

- onChange && onChange('')
+ // 将 div 事件转换为虚假的 ChangeEvent 以符合签名,或改为可选链并传 `undefined`
+ onChange?.('', undefined as unknown as ChangeEvent<HTMLInputElement>)

如果不想构造伪事件,建议在此处 不要调用 onChange,改为让调用方依赖 onClear

🧰 Tools
🪛 Biome (1.9.4)

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🧹 Nitpick comments (8)
src/packages/searchbar/demo.tsx (1)

17-17: 多语言支持完善

添加了新示例的标题翻译,确保在不同语言环境下都能正确显示。中文和繁体中文翻译看起来正确,但英文翻译似乎没有进行本地化,仍保留中文内容。

建议将英文翻译更新为对应的英文描述:

-      title10: '默认值、受控',
+      title10: 'Default Value & Controlled Mode',

Also applies to: 27-27, 37-37

src/packages/searchbar/demos/h5/demo10.tsx (1)

11-25: 默认值(非受控)模式示例

这个示例很好地展示了:

  1. 使用defaultValue属性设置默认值
  2. 通过onItemClick处理默认值项的点击事件
  3. 自定义图标和右侧内容

注意到在onItemClick回调中,将dvalue设置为了固定值"黄瓜"而非基于当前值的动态更新。这种实现可能不符合实际使用场景的需求。

考虑改进onItemClick的处理方式,使其能动态更新值:

onItemClick={(value: string) => {
  console.log('click', value)
-  setDvalue('黄瓜')
+  // 从默认值中移除被点击的项
+  setDvalue(dvalue.split(',').filter(item => item !== value).join(','))
}}
src/packages/searchbar/doc.taro.md (1)

120-121: 更新CSS变量默认值

更新了多个CSS变量的默认值:

  1. 减小了padding值(从6px 16px1px 8px
  2. 更新了背景色为$color-background-sunken
  3. 区分了外部大间距和内部元素间距
  4. 增加了内容区圆角和round模式下的圆角值
  5. 调整了输入区高度和内边距

这些更新使组件样式更加精细和现代化。

注意:文档中有一处小错误,在\--nutui-searchbar-input-padding描述中,"搜索框输入区padding"包含了重复的英文单词,可以考虑改为中文表述以保持一致性。

-| \--nutui-searchbar-input-padding | 搜索框输入区padding | `0 0 0 8px` |
+| \--nutui-searchbar-input-padding | 搜索框输入区内边距 | `0 0 0 8px` |

Also applies to: 123-124, 127-130

🧰 Tools
🪛 LanguageTool

[locale-violation] ~121-~121: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...ing值 | 1px 8px | | --nutui-searchbar-background | 搜索框背景色 | $color-background-sunken |...

(GL_BARBARISM_REPLACE)


[locale-violation] ~121-~121: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...--nutui-searchbar-background | 搜索框背景色 | $color-background-sunken | | --nutui-searchbar-color | ...

(GL_BARBARISM_REPLACE)

src/packages/searchbar/searchbar.tsx (1)

207-214: focus 状态样式判断条件过于宽泛
当前根据 left || backable 判定是否添加 -focus,意味着只要存在左侧内容就会触发,
与“聚焦”语义不符。建议改为监听 input 的实际 focus/blur 状态或 autoFocus

src/packages/searchbar/searchbar.scss (2)

12-16: 全局 icon 尺寸统一可能影响自定义大小
.nut-searchbar .nut-icon 统一设置 width/height/font-size
会覆盖用户在 left/right/rightIn 等插槽自定义的 icon 大小。
可以只对 leftIn/rightIn/clear 等特定内置 icon 设定,避免误伤。

// 示例:限定作用域而非通配
.nut-searchbar-icon {
  width: $searchbar-icon-size;
  height: $searchbar-icon-size;
  font-size: $searchbar-icon-size;
}

82-105: 默认值列表位置写死,缺乏适配性
.nut-searchbar-values 使用 top: 9px; left: 6px; 会在不同尺寸主题下产生错位,
建议改为使用 padding-leftflex + gap 方案,或暴露 CSS 变量方便业务方覆盖。

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

99-101: 文字排版错误 – “搜搜框”
| right | 搜搜框右侧区域 → 应为 搜索框
请修正以保持专业性。

src/packages/searchbar/doc.zh-TW.md (1)

99-101: 排版錯誤 – 「搜搜框」
| right | 搜搜框右側區域 → 應為 搜索框 / 搜尋框
請修正以避免文字錯誤。

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between bc1f644 and 63ae5b5.

📒 Files selected for processing (13)
  • src/packages/searchbar/demo.tsx (3 hunks)
  • src/packages/searchbar/demos/h5/demo1.tsx (1 hunks)
  • src/packages/searchbar/demos/h5/demo10.tsx (1 hunks)
  • src/packages/searchbar/demos/h5/demo3.tsx (1 hunks)
  • src/packages/searchbar/demos/h5/demo5.tsx (1 hunks)
  • src/packages/searchbar/doc.md (3 hunks)
  • src/packages/searchbar/doc.taro.md (3 hunks)
  • src/packages/searchbar/doc.zh-TW.md (2 hunks)
  • src/packages/searchbar/searchbar.scss (2 hunks)
  • src/packages/searchbar/searchbar.tsx (8 hunks)
  • src/sites/sites-react/doc/docs/react/migrate-from-v2.md (1 hunks)
  • src/styles/variables.scss (1 hunks)
  • src/types/spec/searchbar/base.ts (2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (3)
src/packages/searchbar/demos/h5/demo1.tsx (1)
src/packages/searchbar/searchbar.tsx (1)
  • SearchBar (25-233)
src/packages/searchbar/demos/h5/demo10.tsx (1)
src/packages/searchbar/searchbar.tsx (1)
  • SearchBar (25-233)
src/packages/searchbar/demos/h5/demo5.tsx (1)
src/packages/calendarcard/icon.taro.tsx (1)
  • ArrowLeft (44-44)
🪛 LanguageTool
src/packages/searchbar/doc.md

[locale-violation] ~121-~121: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...ing值 | 1px 8px | | --nutui-searchbar-background | 搜索框背景色 | $color-background-sunken |...

(GL_BARBARISM_REPLACE)


[locale-violation] ~121-~121: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...--nutui-searchbar-background | 搜索框背景色 | $color-background-sunken | | --nutui-searchbar-color | ...

(GL_BARBARISM_REPLACE)


[locale-violation] ~123-~123: 'gap' é un xenismo. É preferíbel dicir "hiato"
Context: ...| $color-title | | --nutui-searchbar-gap | 搜索框外部/大间距 | 12px | | --nutui-searc...

(GL_BARBARISM_REPLACE)


[locale-violation] ~124-~124: 'gap' é un xenismo. É preferíbel dicir "hiato"
Context: ...距 | 12px | | --nutui-searchbar-inner-gap | 搜索框内部元素间的间距 | 12px | | --nutui-sea...

(GL_BARBARISM_REPLACE)


[locale-violation] ~126-~126: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...ze-base| | \--nutui-searchbar-content-background | 搜索框中间内容区的背景色 |$color-background-ove...

(GL_BARBARISM_REPLACE)


[locale-violation] ~126-~126: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...bar-content-background | 搜索框中间内容区的背景色 | $color-background-overlay | | --nutui-searchbar-content...

(GL_BARBARISM_REPLACE)


[locale-violation] ~129-~129: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...d模式下的圆角 | 19px | | --nutui-searchbar-input-height | 搜索框输入区高度 | 38px | | --nutui...

(GL_BARBARISM_REPLACE)


[locale-violation] ~130-~130: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...索框输入区高度 | 38px | | --nutui-searchbar-input-padding | 搜索框输入区padding | 0 0 0 8px |...

(GL_BARBARISM_REPLACE)


[duplication] ~130-~130: Posíbel erro tipográfico: hai unha palabra repetida.
Context: ...archbar-input-padding | 搜索框输入区padding | 0 0 0 8px | | --nutui-searchbar-input-tex...

(WORD_REPETITION)

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

[locale-violation] ~121-~121: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...ing值 | 1px 8px | | --nutui-searchbar-background | 搜索框背景色 | $color-background-sunken |...

(GL_BARBARISM_REPLACE)


[locale-violation] ~121-~121: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...--nutui-searchbar-background | 搜索框背景色 | $color-background-sunken | | --nutui-searchbar-color | ...

(GL_BARBARISM_REPLACE)


[locale-violation] ~123-~123: 'gap' é un xenismo. É preferíbel dicir "hiato"
Context: ...| $color-title | | --nutui-searchbar-gap | 搜索框外部/大間距 | 12px | | --nutui-searc...

(GL_BARBARISM_REPLACE)


[locale-violation] ~124-~124: 'gap' é un xenismo. É preferíbel dicir "hiato"
Context: ...距 | 12px | | --nutui-searchbar-inner-gap | 搜索框內部元素間的間距 | 12px | | --nutui-sea...

(GL_BARBARISM_REPLACE)


[locale-violation] ~126-~126: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...ze-base| | \--nutui-searchbar-content-background | 搜索框中間內容區的背景色 |$color-background-ove...

(GL_BARBARISM_REPLACE)


[locale-violation] ~126-~126: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...bar-content-background | 搜索框中間內容區的背景色 | $color-background-overlay | | --nutui-searchbar-content...

(GL_BARBARISM_REPLACE)


[locale-violation] ~129-~129: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...d模式下的圓角 | 19px | | --nutui-searchbar-input-height | 搜索框輸入區高度 | 38px | | --nutui...

(GL_BARBARISM_REPLACE)


[locale-violation] ~130-~130: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...索框輸入區高度 | 38px | | --nutui-searchbar-input-padding | 搜索框輸入區padding | 0 0 0 8px |...

(GL_BARBARISM_REPLACE)


[duplication] ~130-~130: Posíbel erro tipográfico: hai unha palabra repetida.
Context: ...archbar-input-padding | 搜索框輸入區padding | 0 0 0 8px | | --nutui-searchbar-input-tex...

(WORD_REPETITION)

src/packages/searchbar/doc.taro.md

[locale-violation] ~121-~121: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...ing值 | 1px 8px | | --nutui-searchbar-background | 搜索框背景色 | $color-background-sunken |...

(GL_BARBARISM_REPLACE)


[locale-violation] ~121-~121: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...--nutui-searchbar-background | 搜索框背景色 | $color-background-sunken | | --nutui-searchbar-color | ...

(GL_BARBARISM_REPLACE)


[locale-violation] ~123-~123: 'gap' é un xenismo. É preferíbel dicir "hiato"
Context: ...| $color-title | | --nutui-searchbar-gap | 搜索框外部/大间距 | 12px | | --nutui-searc...

(GL_BARBARISM_REPLACE)


[locale-violation] ~124-~124: 'gap' é un xenismo. É preferíbel dicir "hiato"
Context: ...距 | 12px | | --nutui-searchbar-inner-gap | 搜索框内部元素间的间距 | 12px | | --nutui-sea...

(GL_BARBARISM_REPLACE)


[locale-violation] ~126-~126: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...ze-base| | \--nutui-searchbar-content-background | 搜索框中间内容区的背景色 |$color-background-ove...

(GL_BARBARISM_REPLACE)


[locale-violation] ~126-~126: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...bar-content-background | 搜索框中间内容区的背景色 | $color-background-overlay | | --nutui-searchbar-content...

(GL_BARBARISM_REPLACE)


[locale-violation] ~129-~129: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...d模式下的圆角 | 19px | | --nutui-searchbar-input-height | 搜索框输入区高度 | 38px | | --nutui...

(GL_BARBARISM_REPLACE)


[locale-violation] ~130-~130: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...索框输入区高度 | 38px | | --nutui-searchbar-input-padding | 搜索框输入区padding | 0 0 0 8px |...

(GL_BARBARISM_REPLACE)


[duplication] ~130-~130: Posíbel erro tipográfico: hai unha palabra repetida.
Context: ...archbar-input-padding | 搜索框输入区padding | 0 0 0 8px | | --nutui-searchbar-input-tex...

(WORD_REPETITION)

🪛 Biome (1.9.4)
src/packages/searchbar/searchbar.tsx

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: test
🔇 Additional comments (21)
src/styles/variables.scss (6)

1929-1929: 更新了SearchBar的内边距,使其更紧凑

将SearchBar的内边距从6px 16px调整为1px 8px,使组件布局更加紧凑,这与SearchBar的受控和默认值特性更新相匹配。


1932-1932: 更新了SearchBar的背景色,提高可辨识度

将背景色从$color-background更改为$color-background-sunken,增强了SearchBar与周围元素的视觉区分度。


1935-1936: 优化了SearchBar的间距设置

  1. 将主间距从16px缩小至12px
  2. 新增了$searchbar-inner-gap变量设为8px,用于内部元素间距

这种差异化间距设置使组件层次结构更清晰,外部元素间距稍大,内部元素间距稍小,符合设计规范。


1947-1947: 增加了SearchBar的圆角半径,提升现代感

将内容圆角从4px增加至8px,圆形搜索框圆角从18px增加至19px,使组件更加现代化,视觉效果更佳。

Also applies to: 1951-1951


1953-1958: 新增了SearchBar的图标和输入框样式变量

新增了3个重要变量:

  1. $searchbar-icon-size: 20px - 统一图标尺寸
  2. $searchbar-input-height: 38px - 定义输入框高度
  3. $searchbar-input-padding: 0 0 0 8px - 输入框内边距

这些变量增强了组件的一致性和可配置性,支持新的受控和默认值功能所需的UI布局。


1965-1965: 更新了输入光标颜色,增强品牌一致性

将输入框光标颜色从$color-title更改为$color-primary,使其与品牌主色保持一致,提升用户体验。

src/packages/searchbar/demos/h5/demo3.tsx (1)

12-12: 更新了主题配置中的内容背景色

将搜索框内容区背景色从灰色(#eee)调整为白色(#fff),使搜索框在自定义主题下视觉效果更加清爽。此修改与组件整体样式更新保持一致。

src/packages/searchbar/demos/h5/demo5.tsx (2)

11-12: 移除了图标组件的尺寸属性

移除了ArrowLeftCloseMore图标的尺寸属性,改为使用全局样式统一控制。这与变量文件中新增的$searchbar-icon-size相对应,提高了组件样式的一致性和可维护性。

Also applies to: 22-22


26-31: 保留了Photograph图标的点击事件处理

移除了Photograph图标的尺寸属性,但保留了点击事件处理,确保功能不受样式调整影响。这是一个良好的优化,既统一了样式又保持了交互功能。

src/sites/sites-react/doc/docs/react/migrate-from-v2.md (1)

183-188: 新增了SearchBar组件的迁移指南

清晰地补充了SearchBar组件的新特性说明,包括:

  1. value属性支持受控模式
  2. 新增defaultValue属性,支持默认值和多默认值(以逗号分隔)
  3. 新增onItemClick回调,用于处理点击默认值项目的关闭图标事件

文档更新全面且准确,有助于用户理解并使用这些新功能。

src/types/spec/searchbar/base.ts (1)

7-7: 扩展了BaseSearchBar接口,增加新属性支持

在BaseSearchBar接口中新增了两个属性:

  1. defaultValue: string - 用于支持非受控模式下的默认值
  2. onItemClick: (value: string) => void - 用于处理点击默认值项的回调函数

这些类型定义与组件新功能完全匹配,确保了TypeScript类型安全性和API一致性。

Also applies to: 26-26

src/packages/searchbar/demo.tsx (2)

11-11: 引入了新的示例以展示受控和默认值的用法

正确导入了Demo10组件,这将用于展示SearchBar的新功能。


52-53: 正确整合了新示例到演示页面

新增的Demo10示例被正确地添加到了演示页面中,并使用对应的翻译标题。

src/packages/searchbar/demos/h5/demo1.tsx (2)

2-2: 合理引入相关组件

正确导入了所需的图标和分割线组件,用于增强SearchBar的视觉表现。

Also applies to: 4-4


9-20: 基础用法示例优化

新版基础用法示例更加丰富,展示了两种不同配置的SearchBar:

  1. 简单配置:带placeholder和右侧文本
  2. 复杂配置:带左侧图标、placeholder和自定义右侧内容(包含图标、分隔线和文本)

这种展示方式更全面地展示了组件的基础能力,有助于用户理解组件的灵活性。

src/packages/searchbar/demos/h5/demo10.tsx (3)

1-5: 组件引入和状态声明

正确导入了React hooks和所需组件,设置了适当的初始状态用于展示受控和非受控用法。


7-8: 状态初始化设置

合理设置了两种状态变量:

  • dvalue:用于非受控模式,初始化为逗号分隔的多值
  • value:用于受控模式,初始化为单个值

这样的设置有效地展示了组件的两种使用模式。


26-42: 受控模式示例

这个示例很好地展示了:

  1. 使用valueonChange实现受控模式
  2. 使用autoFocus属性自动聚焦
  3. 自定义复杂的右侧内容,包含图标和按钮

实现正确,展示了受控组件的典型用法。

src/packages/searchbar/doc.taro.md (3)

89-90: 添加并完善属性文档

适当更新了value属性的描述,明确标注其为"受控"属性,并新增了defaultValue属性的说明,清晰解释了它支持通过逗号分隔成多个值。这有助于开发者理解两种使用模式的区别。


101-101: 简化默认图标配置

更新了leftIn属性的默认值说明,移除了之前显式设置的尺寸属性,使文档更加简洁。


109-109: 添加新事件回调文档

新增了onItemClick事件的说明,清晰解释了其触发条件和参数。

Comment on lines 72 to 75
useEffect(() => {
setValue(defaultValue)
}, [defaultValue])

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

defaultValue 变更副作用可能破坏受控模式
useEffect 每当 defaultValue 变化即调用 setValue
若组件已经处于“受控”(由 value 驱动) 状态,会被意外覆盖。

-useEffect(() => {
-  setValue(defaultValue)
-}, [defaultValue])
+useEffect(() => {
+  // 仅在组件非受控且 defaultValue 有效时同步内部状态
+  if (outerValue === undefined && defaultValue !== undefined) {
+    setValue(defaultValue)
+  }
+}, [defaultValue, outerValue])

这样可以避免父组件通过 value 控制时被打断。


让我们先查看 src/packages/searchbar/searchbar.tsx 中的组件实现,以确认 defaultValueouterValue 及其状态管理逻辑:


🏁 Script executed:

#!/bin/bash
sed -n '1,200p' src/packages/searchbar/searchbar.tsx

Length of output: 4819


我们先查看 usePropsValue 的实现,以确认它如何处理 valuedefaultValue


🏁 Script executed:

#!/bin/bash
rg "usePropsValue" -n src

Length of output: 12844


继续查看 usePropsValue 的完整实现,以确认它如何处理 defaultValue


🏁 Script executed:

#!/bin/bash
sed -n '1,200p' src/hooks/use-props-value.ts

Length of output: 977


🏁 Script executed:

#!/bin/bash
rg "ComponentDefaults" -n src

Length of output: 26793


优化 defaultValue 同步逻辑,避免受控模式被覆盖

当前的 useEffect 在 defaultValue 变化时无条件调用 setValue(defaultValue),会导致组件处于受控(传入 value)时触发多余更新甚至覆盖。建议改为:仅在非受控(outerValue === undefined)且 defaultValue 有效时再同步内部状态。

待修改位置:

  • 文件:src/packages/searchbar/searchbar.tsx
  • 行号:约 72–75
-useEffect(() => {
-  setValue(defaultValue)
-}, [defaultValue])
+useEffect(() => {
+  // 仅在组件非受控且 defaultValue 有效时同步内部状态
+  if (outerValue === undefined && defaultValue !== undefined) {
+    setValue(defaultValue)
+  }
+}, [defaultValue, outerValue])
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
useEffect(() => {
setValue(defaultValue)
}, [defaultValue])
useEffect(() => {
// 仅在组件非受控且 defaultValue 有效时同步内部状态
if (outerValue === undefined && defaultValue !== undefined) {
setValue(defaultValue)
}
}, [defaultValue, outerValue])

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 (4)
src/packages/searchbar/demo.tsx (1)

17-17: 建议完善英文翻译

为中文和繁体中文添加了"默认值、受控"的翻译,但英文版本仍使用了中文。

-      title10: '默认值、受控',
+      title10: 'Default Value & Controlled Mode',

Also applies to: 27-27, 37-37

src/packages/searchbar/demos/h5/demo10.tsx (1)

15-18: 确保控制台日志在生产环境中被移除

在onItemClick回调中包含console.log语句,虽然这在示例中有助于演示,但应确保这类调试代码不会进入生产环境。

onItemClick={(value: string) => {
-  console.log('click', value)
  setDvalue('黄瓜')
}}
src/packages/searchbar/searchbar.tsx (2)

81-97: 优化事件处理函数

重命名事件处理函数采用 handle 前缀,使命名更规范,同时简化了回调函数的调用方式,提高了代码可读性和维护性。

注意:事件处理函数中的可选链判断可以进一步优化。

你可以考虑使用可选链操作符来简化代码:

-  const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
-    const { value } = event.target
-    onChange && onChange(value, event)
-    setValue(value)
-  }
+  const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
+    const { value } = event.target
+    onChange?.(value, event)
+    setValue(value)
+  }
🧰 Tools
🪛 Biome (1.9.4)

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


190-193: 优化清除值函数逻辑

简化了条件判断语句,并确保在清除值时调用 onChange 回调,保持了组件行为的一致性。

注意:这里的 onChange 调用也可以使用可选链优化。

你可以使用可选链操作符进一步简化代码:

-    onChange && onChange('')
+    onChange?.('')
🧰 Tools
🪛 Biome (1.9.4)

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 193-193: 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 bc1f644 and 63ae5b5.

📒 Files selected for processing (13)
  • src/packages/searchbar/demo.tsx (3 hunks)
  • src/packages/searchbar/demos/h5/demo1.tsx (1 hunks)
  • src/packages/searchbar/demos/h5/demo10.tsx (1 hunks)
  • src/packages/searchbar/demos/h5/demo3.tsx (1 hunks)
  • src/packages/searchbar/demos/h5/demo5.tsx (1 hunks)
  • src/packages/searchbar/doc.md (3 hunks)
  • src/packages/searchbar/doc.taro.md (3 hunks)
  • src/packages/searchbar/doc.zh-TW.md (2 hunks)
  • src/packages/searchbar/searchbar.scss (2 hunks)
  • src/packages/searchbar/searchbar.tsx (8 hunks)
  • src/sites/sites-react/doc/docs/react/migrate-from-v2.md (1 hunks)
  • src/styles/variables.scss (1 hunks)
  • src/types/spec/searchbar/base.ts (2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
src/packages/searchbar/demos/h5/demo5.tsx (1)
src/packages/calendarcard/icon.taro.tsx (1)
  • ArrowLeft (44-44)
src/packages/searchbar/demos/h5/demo10.tsx (1)
src/packages/searchbar/searchbar.tsx (1)
  • SearchBar (25-233)
🪛 LanguageTool
src/packages/searchbar/doc.md

[locale-violation] ~121-~121: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...ing值 | 1px 8px | | --nutui-searchbar-background | 搜索框背景色 | $color-background-sunken |...

(GL_BARBARISM_REPLACE)


[locale-violation] ~121-~121: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...--nutui-searchbar-background | 搜索框背景色 | $color-background-sunken | | --nutui-searchbar-color | ...

(GL_BARBARISM_REPLACE)


[locale-violation] ~123-~123: 'gap' é un xenismo. É preferíbel dicir "hiato"
Context: ...| $color-title | | --nutui-searchbar-gap | 搜索框外部/大间距 | 12px | | --nutui-searc...

(GL_BARBARISM_REPLACE)


[locale-violation] ~124-~124: 'gap' é un xenismo. É preferíbel dicir "hiato"
Context: ...距 | 12px | | --nutui-searchbar-inner-gap | 搜索框内部元素间的间距 | 12px | | --nutui-sea...

(GL_BARBARISM_REPLACE)


[locale-violation] ~126-~126: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...ze-base| | \--nutui-searchbar-content-background | 搜索框中间内容区的背景色 |$color-background-ove...

(GL_BARBARISM_REPLACE)


[locale-violation] ~126-~126: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...bar-content-background | 搜索框中间内容区的背景色 | $color-background-overlay | | --nutui-searchbar-content...

(GL_BARBARISM_REPLACE)


[locale-violation] ~129-~129: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...d模式下的圆角 | 19px | | --nutui-searchbar-input-height | 搜索框输入区高度 | 38px | | --nutui...

(GL_BARBARISM_REPLACE)


[locale-violation] ~130-~130: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...索框输入区高度 | 38px | | --nutui-searchbar-input-padding | 搜索框输入区padding | 0 0 0 8px |...

(GL_BARBARISM_REPLACE)


[duplication] ~130-~130: Posíbel erro tipográfico: hai unha palabra repetida.
Context: ...archbar-input-padding | 搜索框输入区padding | 0 0 0 8px | | --nutui-searchbar-input-tex...

(WORD_REPETITION)

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

[locale-violation] ~121-~121: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...ing值 | 1px 8px | | --nutui-searchbar-background | 搜索框背景色 | $color-background-sunken |...

(GL_BARBARISM_REPLACE)


[locale-violation] ~121-~121: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...--nutui-searchbar-background | 搜索框背景色 | $color-background-sunken | | --nutui-searchbar-color | ...

(GL_BARBARISM_REPLACE)


[locale-violation] ~123-~123: 'gap' é un xenismo. É preferíbel dicir "hiato"
Context: ...| $color-title | | --nutui-searchbar-gap | 搜索框外部/大間距 | 12px | | --nutui-searc...

(GL_BARBARISM_REPLACE)


[locale-violation] ~124-~124: 'gap' é un xenismo. É preferíbel dicir "hiato"
Context: ...距 | 12px | | --nutui-searchbar-inner-gap | 搜索框內部元素間的間距 | 12px | | --nutui-sea...

(GL_BARBARISM_REPLACE)


[locale-violation] ~126-~126: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...ze-base| | \--nutui-searchbar-content-background | 搜索框中間內容區的背景色 |$color-background-ove...

(GL_BARBARISM_REPLACE)


[locale-violation] ~126-~126: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...bar-content-background | 搜索框中間內容區的背景色 | $color-background-overlay | | --nutui-searchbar-content...

(GL_BARBARISM_REPLACE)


[locale-violation] ~129-~129: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...d模式下的圓角 | 19px | | --nutui-searchbar-input-height | 搜索框輸入區高度 | 38px | | --nutui...

(GL_BARBARISM_REPLACE)


[locale-violation] ~130-~130: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...索框輸入區高度 | 38px | | --nutui-searchbar-input-padding | 搜索框輸入區padding | 0 0 0 8px |...

(GL_BARBARISM_REPLACE)


[duplication] ~130-~130: Posíbel erro tipográfico: hai unha palabra repetida.
Context: ...archbar-input-padding | 搜索框輸入區padding | 0 0 0 8px | | --nutui-searchbar-input-tex...

(WORD_REPETITION)

src/packages/searchbar/doc.taro.md

[locale-violation] ~121-~121: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...ing值 | 1px 8px | | --nutui-searchbar-background | 搜索框背景色 | $color-background-sunken |...

(GL_BARBARISM_REPLACE)


[locale-violation] ~121-~121: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...--nutui-searchbar-background | 搜索框背景色 | $color-background-sunken | | --nutui-searchbar-color | ...

(GL_BARBARISM_REPLACE)


[locale-violation] ~123-~123: 'gap' é un xenismo. É preferíbel dicir "hiato"
Context: ...| $color-title | | --nutui-searchbar-gap | 搜索框外部/大间距 | 12px | | --nutui-searc...

(GL_BARBARISM_REPLACE)


[locale-violation] ~124-~124: 'gap' é un xenismo. É preferíbel dicir "hiato"
Context: ...距 | 12px | | --nutui-searchbar-inner-gap | 搜索框内部元素间的间距 | 12px | | --nutui-sea...

(GL_BARBARISM_REPLACE)


[locale-violation] ~126-~126: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...ze-base| | \--nutui-searchbar-content-background | 搜索框中间内容区的背景色 |$color-background-ove...

(GL_BARBARISM_REPLACE)


[locale-violation] ~126-~126: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...bar-content-background | 搜索框中间内容区的背景色 | $color-background-overlay | | --nutui-searchbar-content...

(GL_BARBARISM_REPLACE)


[locale-violation] ~129-~129: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...d模式下的圆角 | 19px | | --nutui-searchbar-input-height | 搜索框输入区高度 | 38px | | --nutui...

(GL_BARBARISM_REPLACE)


[locale-violation] ~130-~130: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...索框输入区高度 | 38px | | --nutui-searchbar-input-padding | 搜索框输入区padding | 0 0 0 8px |...

(GL_BARBARISM_REPLACE)


[duplication] ~130-~130: Posíbel erro tipográfico: hai unha palabra repetida.
Context: ...archbar-input-padding | 搜索框输入区padding | 0 0 0 8px | | --nutui-searchbar-input-tex...

(WORD_REPETITION)

🪛 Biome (1.9.4)
src/packages/searchbar/searchbar.tsx

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🔇 Additional comments (55)
src/styles/variables.scss (4)

1929-1937: 样式间距和背景变量更新

搜索栏样式变量更新使组件设计更加精细:

  • 边距从 6px 16px 调整为 1px 8px,创造更紧凑的外观
  • 背景色从 $color-background 更改为 $color-background-sunken,提供更好的层次感
  • 元素间距从 16px 减少到 12px,使布局更加紧凑
  • 新增 $searchbar-inner-gap 变量,提供内部元素 8px 的间距控制

这些变化使搜索栏在各种界面布局中更加协调和精致。


1947-1952: 圆角半径优化

圆角半径的调整使搜索栏外观更加现代化:

  • 内容边框圆角从 4px 增加到 8px
  • 圆形边框圆角从 18px 轻微调整到 19px

这些微小但重要的调整使组件符合当前设计趋势,提供更柔和的视觉效果。


1953-1958: 新增图标和输入框变量

新增了重要的样式变量,提高了组件的一致性和可定制性:

  • $searchbar-icon-size:标准化图标尺寸为 20px
  • $searchbar-input-height:设置输入框高度为 38px
  • $searchbar-input-padding:指定输入框内边距为 0 0 0 8px

这些新变量使开发者能够更容易地保持风格一致,并支持新增的默认值显示功能。


1965-1966: 更新输入光标颜色

光标颜色从 $color-title 更改为 $color-primary,使其与品牌色一致,提高了用户在输入时的视觉反馈。

src/packages/searchbar/demos/h5/demo3.tsx (1)

12-12: 主题配置背景色优化

将搜索栏内容背景色从 #eee 更改为 #fff,使其在主题定制示例中更具视觉吸引力,同时展示了组件的可配置性。这种白色背景更好地突出内容,并与整体视觉设计保持一致。

src/types/spec/searchbar/base.ts (2)

7-7: 新增 defaultValue 属性

添加了 defaultValue 字符串属性,支持设置搜索栏的默认值。这提高了组件的灵活性,允许开发者为搜索栏设置初始状态,特别是在需要显示多个默认值的场景下。


26-26: 新增 onItemClick 回调函数

添加了 onItemClick 回调函数,用于处理点击默认值项的事件。这个回调接收被点击项的值作为参数,使开发者能够实现交互式的默认值管理,例如删除或选择特定项。

src/packages/searchbar/demos/h5/demo5.tsx (1)

11-12: 移除图标显式尺寸属性

移除了图标组件上的硬编码宽度和高度属性,遵循了更好的实践方式。这使图标可以:

  1. 通过 CSS 变量自动继承尺寸,支持主题和响应式设计
  2. 利用新增的 $searchbar-icon-size 变量保持一致的尺寸
  3. 减少重复代码并提高维护性

建议确保项目文档中明确说明这些图标现在的尺寸由 CSS 变量控制。

Also applies to: 22-22

src/sites/sites-react/doc/docs/react/migrate-from-v2.md (1)

183-188: 文档更新符合新功能实现

这部分文档清晰地说明了SearchBar组件的新增功能,支持受控模式、默认值显示和默认值项的交互处理。文档内容与代码实现保持一致。

src/packages/searchbar/demo.tsx (2)

11-11: 正确导入新的示例组件

成功导入了新的Demo10组件,用于展示SearchBar的默认值和受控功能。


52-54: 合理安排示例顺序

将默认值和受控示例放在基础用法之后,符合从简单到复杂的示例组织原则,便于用户理解。

src/packages/searchbar/demos/h5/demo10.tsx (4)

1-5: 导入了必要的组件和钩子

正确导入了React的useState钩子、图标组件、SearchBar和Button组件,为示例提供了必要的依赖。


6-9: 初始化状态逻辑清晰

使用useState钩子分别初始化了defaultValue和value状态,用于演示非受控和受控模式。


11-25: 默认值功能展示完整

第一个SearchBar组件展示了新增的defaultValue和onItemClick功能,设置了backable、清除了左侧内容、添加了右侧图标,演示全面。


26-42: 受控模式实现正确

第二个SearchBar组件正确实现了受控模式,使用value和onChange配合,同时启用了autoFocus属性和自定义右侧内容,展示了组件的灵活性。

src/packages/searchbar/demos/h5/demo1.tsx (2)

2-4: 添加了必要的图标和分隔符组件

导入了Photograph和Scan图标组件以及Divider分隔符组件,增强了基础示例的视觉效果和功能展示。


9-20: 丰富了基础示例的多样性

将原先的简单示例扩展为两个不同配置的示例,分别展示了简单文本和复杂布局的右侧内容,以及左侧图标的使用,增强了基础示例的参考价值。

src/packages/searchbar/doc.zh-TW.md (6)

89-90: 文档增加 value 和 defaultValue 属性,清晰地区分受控与非受控用法

属性扩展合理,并明确标注了 value 为受控方式,同时新增 defaultValue 支持非受控使用和多个默认值展示,提升了组件的灵活性。


101-101: 简化了 leftIn 属性的默认图标展示

leftIn 属性的默认值从明确指定尺寸的图标简化为 <Search />,使代码更简洁,同时保持功能一致性。


109-109: 新增 onItemClick 回调支持默认值点击交互

添加 onItemClick 事件处理函数,使开发者可以响应用户点击默认值 X 号的操作,增强了组件的交互性。


119-121: 优化搜索框样式变量配置

调整了外观相关样式变量,减小了内边距并更新了背景色,使组件更美观紧凑。

🧰 Tools
🪛 LanguageTool

[locale-violation] ~121-~121: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...ing值 | 1px 8px | | --nutui-searchbar-background | 搜索框背景色 | $color-background-sunken |...

(GL_BARBARISM_REPLACE)


[locale-violation] ~121-~121: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...--nutui-searchbar-background | 搜索框背景色 | $color-background-sunken | | --nutui-searchbar-color | ...

(GL_BARBARISM_REPLACE)


123-124: 完善间距变量设计

增加了内部元素间距变量 inner-gap,同时调整外部间距值,使布局更加合理清晰。

🧰 Tools
🪛 LanguageTool

[locale-violation] ~123-~123: 'gap' é un xenismo. É preferíbel dicir "hiato"
Context: ...| $color-title | | --nutui-searchbar-gap | 搜索框外部/大間距 | 12px | | --nutui-searc...

(GL_BARBARISM_REPLACE)


[locale-violation] ~124-~124: 'gap' é un xenismo. É preferíbel dicir "hiato"
Context: ...距 | 12px | | --nutui-searchbar-inner-gap | 搜索框內部元素間的間距 | 12px | | --nutui-sea...

(GL_BARBARISM_REPLACE)


127-130: 优化圆角和输入区域尺寸

增大了内容区圆角和输入区高度,并调整了输入区的内边距,使组件在视觉上更加现代化且提升了用户体验。

🧰 Tools
🪛 LanguageTool

[locale-violation] ~129-~129: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...d模式下的圓角 | 19px | | --nutui-searchbar-input-height | 搜索框輸入區高度 | 38px | | --nutui...

(GL_BARBARISM_REPLACE)


[locale-violation] ~130-~130: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...索框輸入區高度 | 38px | | --nutui-searchbar-input-padding | 搜索框輸入區padding | 0 0 0 8px |...

(GL_BARBARISM_REPLACE)


[duplication] ~130-~130: Posíbel erro tipográfico: hai unha palabra repetida.
Context: ...archbar-input-padding | 搜索框輸入區padding | 0 0 0 8px | | --nutui-searchbar-input-tex...

(WORD_REPETITION)

src/packages/searchbar/doc.taro.md (5)

89-90: 完善属性说明,新增 defaultValue 支持

文档更新清晰地标明了 value 为受控模式,并添加了 defaultValue 属性支持通过逗号分隔的多个默认值,增强了组件的灵活性。


101-101: 简化 leftIn 属性的默认值

将默认搜索图标从特定尺寸简化为 <Search />,使代码更简洁,同时保持了功能一致性。


109-109: 添加 onItemClick 回调提升交互体验

新增了 onItemClick 事件处理函数,支持用户点击默认值 X 号时的交互,使组件更加完善。


120-124: 调整样式变量提升外观

调整了内边距、背景色和间距相关变量,新增了内部元素间距变量,使组件布局更加合理。

🧰 Tools
🪛 LanguageTool

[locale-violation] ~121-~121: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...ing值 | 1px 8px | | --nutui-searchbar-background | 搜索框背景色 | $color-background-sunken |...

(GL_BARBARISM_REPLACE)


[locale-violation] ~121-~121: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...--nutui-searchbar-background | 搜索框背景色 | $color-background-sunken | | --nutui-searchbar-color | ...

(GL_BARBARISM_REPLACE)


[locale-violation] ~123-~123: 'gap' é un xenismo. É preferíbel dicir "hiato"
Context: ...| $color-title | | --nutui-searchbar-gap | 搜索框外部/大间距 | 12px | | --nutui-searc...

(GL_BARBARISM_REPLACE)


[locale-violation] ~124-~124: 'gap' é un xenismo. É preferíbel dicir "hiato"
Context: ...距 | 12px | | --nutui-searchbar-inner-gap | 搜索框内部元素间的间距 | 12px | | --nutui-sea...

(GL_BARBARISM_REPLACE)


127-130: 优化组件圆角和输入区域

增大了内容区圆角值和输入区高度,调整了输入区内边距,使组件视觉效果更加现代化。

🧰 Tools
🪛 LanguageTool

[locale-violation] ~129-~129: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...d模式下的圆角 | 19px | | --nutui-searchbar-input-height | 搜索框输入区高度 | 38px | | --nutui...

(GL_BARBARISM_REPLACE)


[locale-violation] ~130-~130: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...索框输入区高度 | 38px | | --nutui-searchbar-input-padding | 搜索框输入区padding | 0 0 0 8px |...

(GL_BARBARISM_REPLACE)


[duplication] ~130-~130: Posíbel erro tipográfico: hai unha palabra repetida.
Context: ...archbar-input-padding | 搜索框输入区padding | 0 0 0 8px | | --nutui-searchbar-input-tex...

(WORD_REPETITION)

src/packages/searchbar/doc.md (5)

89-90: 完善属性文档,优化受控和非受控模式说明

明确了 value 属性为受控模式,并新增 defaultValue 属性支持多个默认值展示,文档描述清晰准确。


101-101: 简化 leftIn 属性默认图标

将默认搜索图标从特定尺寸简化为 <Search />,保持与组件实现一致,提高代码可读性。


109-109: 新增事件处理回调增强组件交互性

添加 onItemClick 回调函数,使开发者能够响应用户对默认值项的点击操作,增强了组件的功能完整性。


120-124: 优化样式变量定义与默认值

调整了内边距、背景色和间距相关变量,新增了内部元素间的间距变量,使组件布局更加合理。

🧰 Tools
🪛 LanguageTool

[locale-violation] ~121-~121: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...ing值 | 1px 8px | | --nutui-searchbar-background | 搜索框背景色 | $color-background-sunken |...

(GL_BARBARISM_REPLACE)


[locale-violation] ~121-~121: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...--nutui-searchbar-background | 搜索框背景色 | $color-background-sunken | | --nutui-searchbar-color | ...

(GL_BARBARISM_REPLACE)


[locale-violation] ~123-~123: 'gap' é un xenismo. É preferíbel dicir "hiato"
Context: ...| $color-title | | --nutui-searchbar-gap | 搜索框外部/大间距 | 12px | | --nutui-searc...

(GL_BARBARISM_REPLACE)


[locale-violation] ~124-~124: 'gap' é un xenismo. É preferíbel dicir "hiato"
Context: ...距 | 12px | | --nutui-searchbar-inner-gap | 搜索框内部元素间的间距 | 12px | | --nutui-sea...

(GL_BARBARISM_REPLACE)


127-130: 提升输入区域视觉体验

增大了内容区圆角、round 模式下的圆角和输入区高度,调整了输入区内边距,使组件外观更加现代美观。

🧰 Tools
🪛 LanguageTool

[locale-violation] ~129-~129: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...d模式下的圆角 | 19px | | --nutui-searchbar-input-height | 搜索框输入区高度 | 38px | | --nutui...

(GL_BARBARISM_REPLACE)


[locale-violation] ~130-~130: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...索框输入区高度 | 38px | | --nutui-searchbar-input-padding | 搜索框输入区padding | 0 0 0 8px |...

(GL_BARBARISM_REPLACE)


[duplication] ~130-~130: Posíbel erro tipográfico: hai unha palabra repetida.
Context: ...archbar-input-padding | 搜索框输入区padding | 0 0 0 8px | | --nutui-searchbar-input-tex...

(WORD_REPETITION)

src/packages/searchbar/searchbar.scss (8)

12-16: 统一设置图标尺寸样式

为图标组件添加了统一的尺寸样式,确保所有图标在组件中保持一致的大小,提升了组件视觉的一致性。


19-28: 优化内容区域样式

为内容区添加了相对定位,更新了内边距设置,并添加了主色边框,使搜索框在视觉上更加突出且美观。


31-36: 更新图标颜色为主题色

调整图标颜色使用主题主色,增强了组件的视觉识别性和与整体设计的一致性。


38-50: 优化左右内部区域样式

更新了左侧图标的右边距和右侧元素的字体样式,添加了对嵌套图标颜色的特殊处理,使布局更加平衡。


52-71: 重构输入框样式

使用 flex 布局优化了输入框容器和输入元素,设置了透明背景、边框清除和统一文本颜色,提升了用户输入体验。


73-80: 优化清除按钮样式

调整了清除按钮的尺寸和颜色,添加了右侧间距,使其更加协调地融入整体设计。


82-105: 新增默认值项展示容器样式

添加了展示默认值的容器样式,支持多个默认值的水平排列显示,每个值项都有独立的背景色和圆角,同时设置了关闭图标的合适样式,增强了组件的功能性和视觉表现。


175-181: 增加焦点状态样式

新增了搜索框焦点状态的样式,调整内边距并使用特殊边框色突出显示,提高了用户操作的视觉反馈。

src/packages/searchbar/searchbar.tsx (14)

2-8: 优化导入和依赖关系

调整了组件的依赖导入,引入 classNames 工具和 usePropsValue 钩子,为支持受控与非受控模式提供基础。同时简化了图标组件的导入。


23-23: 简化默认图标配置

将默认搜索图标简化为 <Search />,移除了不必要的尺寸属性,使代码更加简洁。


35-35: 提升引用命名的语义化

searchRef 重命名为 searchInputRef,更准确地反映了引用的用途,提高了代码可读性。


39-40: 扩展组件 Props 支持新特性

添加了 defaultValueonItemClick 属性,为支持默认值展示和交互提供了接口,增强了组件的功能性。

Also applies to: 60-60


66-70: 使用 usePropsValue 重构状态管理

usePropsValue 钩子替代原有的 useState,更好地处理受控与非受控状态,提升了组件状态管理的稳定性和一致性。


72-74: 增加 defaultValue 变更同步

添加对 defaultValue 属性变更的监听,确保当默认值更新时组件状态能够正确同步,增强了组件的可靠性。


104-104: 使用 classNames 优化类名处理

采用 classNames 库处理条件类名,使类名逻辑更加清晰和统一,提高了代码可维护性。


115-118: 更新事件绑定命名

将事件处理函数的绑定更新为新的命名方式,保持代码一致性。


123-139: 实现默认值渲染功能

新增 renderDefaultValue 方法,支持将逗号分隔的默认值转换为可点击的标签列表展示,并通过 onItemClick 回调处理点击删除操作,显著增强了组件的功能和用户体验。


153-153: 简化返回按钮图标

移除了箭头图标的明确尺寸参数,使用默认尺寸设置,保持与整体风格一致。


161-169: 优化右侧内容渲染逻辑

增强了 renderRightIn 方法,根据内容类型条件性地应用图标样式类,使组件能够更灵活地处理不同类型的右侧内容。


178-178: 函数命名更符合功能语义

handleClear 重命名为 renderClear,更准确地反映了该函数的渲染功能,提高了代码可读性。


207-214: 使用 classNames 统一根元素类名处理

应用 classNames 库处理根元素的条件类名,包括禁用和焦点状态,使类名管理更加清晰和一致。


217-228: 优化渲染逻辑

更新了组件根元素类名应用方式,并改进了内容区域的条件类名处理。添加了对默认值渲染的条件判断,使清除按钮和默认值不会同时显示,提升了用户界面的清晰度。

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: 2

♻️ Duplicate comments (4)
src/packages/searchbar/searchbar.tsx (2)

71-74: 💥 defaultValue 的副作用仍会覆盖受控模式
useEffectdefaultValue 变化时无条件执行 setValue(defaultValue),若外部通过 value 受控驱动组件,将被意外篡改。此前已反馈过同样问题,仍未修复。建议仅在组件处于非受控状态时同步 defaultValue

-useEffect(() => {
-  setValue(defaultValue)
-}, [defaultValue])
+useEffect(() => {
+  // 仅在非受控(outerValue 未定义)且 defaultValue 有效时同步
+  if (outerValue === undefined && defaultValue !== undefined) {
+    setValue(defaultValue)
+  }
+}, [defaultValue, outerValue])

124-131: 🔗 onItemClick 仍缺少可选链保护
点击默认值标签时直接调用 onItemClick(item),当父组件未传该回调会抛异常。此前已留下同样评论,建议改为可选链调用。

- onClick={() => onItemClick(item)}
+ onClick={() => onItemClick?.(item)}
src/packages/searchbar/searchbar.taro.tsx (2)

78-81: 💥 defaultValue 同步逻辑仍会覆盖受控值
与 web 版相同的问题:受控场景下会被 defaultValue 强行覆盖。

-useEffect(() => {
-  setValue(defaultValue)
-}, [defaultValue])
+useEffect(() => {
+  if (outerValue === undefined && defaultValue !== undefined) {
+    setValue(defaultValue)
+  }
+}, [defaultValue, outerValue])

133-141: 🔗 onItemClick 缺少可选链保护
Taro 版本亦存在同样风险,需改为 onItemClick?.(item)

- onClick={() => onItemClick(item)}
+ onClick={() => onItemClick?.(item)}
🧹 Nitpick comments (5)
src/packages/searchbar/demos/h5/demo10.tsx (1)

11-42: 第一个搜索栏实现了默认值与受控值的协同工作

这个搜索栏展示了:

  1. 如何使用 defaultValue 属性展示多个默认值
  2. 如何通过 onItemClick 处理默认值的删除
  3. 如何在聚焦时将默认值转移到输入框
  4. 如何自定义右侧内容

实现了完整的默认值与受控值的交互流程。

但有两处可以优化:

  1. 移除调试用的 console.log 语句
  2. 考虑优化默认值处理逻辑,可以提取为单独的函数提高代码可读性
- onItemClick={(value: string) => {
-   console.log('click', value)
-   if (dvalue) {
-     const arr = dvalue.split(',')
-     const newArr = arr.filter((item: string) => item !== value)
-     const newVal = newArr.length > 1 ? newArr.join(',') : newArr[0]
-     setValue1(newVal)
-     setDvalue(newVal)
-   }
- }}
- onFocus={() => {
-   console.log('focus dvalue', dvalue)
-   if (dvalue) {
-     setValue1(dvalue)
-     setDvalue('')
-   }
- }}
+ onItemClick={handleItemClick}
+ onFocus={handleFocus}

并在组件上方添加处理函数:

const handleItemClick = (value: string) => {
  if (dvalue) {
    const arr = dvalue.split(',')
    const newArr = arr.filter((item: string) => item !== value)
    const newVal = newArr.length > 1 ? newArr.join(',') : newArr[0]
    setValue1(newVal)
    setDvalue(newVal)
  }
}

const handleFocus = () => {
  if (dvalue) {
    setValue1(dvalue)
    setDvalue('')
  }
}
src/packages/searchbar/demos/taro/demo10.tsx (2)

37-42: 右侧图标布局有待优化

在第一个SearchBar的rightInright属性中,同时使用了图标,但布局上可能存在重叠或紧凑的问题。建议考虑添加适当的间距或只保留一个位置的图标。

-        rightIn={
-          <div style={{ display: 'flex', alignItems: 'center' }}>
-            <Photograph color="#505259" />
-          </div>
-        }
-        right={<Category />}
+        rightIn={
+          <div style={{ display: 'flex', alignItems: 'center' }}>
+            <Photograph color="#505259" style={{ marginRight: '8px' }} />
+          </div>
+        }
+        right={<Category style={{ marginLeft: '8px' }} />}

16-25: 默认值删除逻辑可优化

onItemClick处理函数中,当数组长度为1时的处理逻辑可以更简洁。当只有一个元素时,直接使用该元素而不是创建只有一个元素的数组会更高效。

-            const newVal = newArr.length > 1 ? newArr.join(',') : newArr[0]
+            const newVal = newArr.length > 0 ? (newArr.length > 1 ? newArr.join(',') : newArr[0]) : ''

这样修改后,也处理了数组为空的情况,使逻辑更加健壮。

src/packages/searchbar/searchbar.tsx (1)

75-78: ✨ 使用可选链简化空引用判断
searchSelf && searchSelf.focus() / blur() 可改为 searchInputRef.current?.focus() 等写法,减少布尔运算并符合 Biome 建议。

- const searchSelf: HTMLInputElement | null = searchInputRef.current
- searchSelf && searchSelf.focus()
+ searchInputRef.current?.focus()

同理可应用于 blur() 处。

Also applies to: 91-93

🧰 Tools
🪛 Biome (1.9.4)

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

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

82-85: ✨ 使用可选链优化 Ref 调用
可按照 Biome 建议改为 searchInputRef.current?.focus() / blur()

- const searchSelf: HTMLInputElement | null = searchInputRef.current
- searchSelf && searchSelf.focus()
+ searchInputRef.current?.focus()

Also applies to: 101-103

🧰 Tools
🪛 Biome (1.9.4)

[error] 84-84: 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 63ae5b5 and 202063c.

📒 Files selected for processing (20)
  • src/packages/searchbar/demo.taro.tsx (4 hunks)
  • src/packages/searchbar/demo.tsx (3 hunks)
  • src/packages/searchbar/demos/h5/demo1.tsx (1 hunks)
  • src/packages/searchbar/demos/h5/demo10.tsx (1 hunks)
  • src/packages/searchbar/demos/h5/demo2.tsx (1 hunks)
  • src/packages/searchbar/demos/h5/demo3.tsx (1 hunks)
  • src/packages/searchbar/demos/h5/demo4.tsx (1 hunks)
  • src/packages/searchbar/demos/h5/demo5.tsx (1 hunks)
  • src/packages/searchbar/demos/h5/demo6.tsx (3 hunks)
  • src/packages/searchbar/demos/h5/demo7.tsx (1 hunks)
  • src/packages/searchbar/demos/taro/demo1.tsx (1 hunks)
  • src/packages/searchbar/demos/taro/demo10.tsx (1 hunks)
  • src/packages/searchbar/doc.en-US.md (1 hunks)
  • src/packages/searchbar/doc.md (4 hunks)
  • src/packages/searchbar/doc.taro.md (4 hunks)
  • src/packages/searchbar/doc.zh-TW.md (3 hunks)
  • src/packages/searchbar/searchbar.scss (2 hunks)
  • src/packages/searchbar/searchbar.taro.tsx (5 hunks)
  • src/packages/searchbar/searchbar.tsx (8 hunks)
  • src/sites/sites-react/doc/docs/taro/migrate-from-v2.md (1 hunks)
✅ Files skipped from review due to trivial changes (5)
  • src/packages/searchbar/demos/h5/demo7.tsx
  • src/packages/searchbar/demos/h5/demo2.tsx
  • src/packages/searchbar/demos/h5/demo6.tsx
  • src/packages/searchbar/demos/h5/demo4.tsx
  • src/packages/searchbar/doc.en-US.md
🚧 Files skipped from review as they are similar to previous changes (5)
  • src/packages/searchbar/demos/h5/demo3.tsx
  • src/packages/searchbar/demo.tsx
  • src/packages/searchbar/demos/h5/demo5.tsx
  • src/packages/searchbar/demos/h5/demo1.tsx
  • src/packages/searchbar/searchbar.scss
🧰 Additional context used
🧬 Code Graph Analysis (4)
src/packages/searchbar/demos/taro/demo1.tsx (2)
src/packages/searchbar/searchbar.taro.tsx (1)
  • SearchBar (32-231)
src/packages/searchbar/searchbar.tsx (1)
  • SearchBar (25-230)
src/packages/searchbar/demos/h5/demo10.tsx (1)
src/packages/searchbar/searchbar.tsx (1)
  • SearchBar (25-230)
src/packages/searchbar/demos/taro/demo10.tsx (1)
src/packages/searchbar/searchbar.taro.tsx (1)
  • SearchBar (32-231)
src/packages/searchbar/searchbar.tsx (2)
src/hooks/use-props-value.ts (1)
  • usePropsValue (11-35)
src/packages/calendarcard/icon.taro.tsx (1)
  • ArrowLeft (44-44)
🪛 Biome (1.9.4)
src/packages/searchbar/searchbar.taro.tsx

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

src/packages/searchbar/searchbar.tsx

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🪛 LanguageTool
src/packages/searchbar/doc.md

[locale-violation] ~127-~127: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...ing值 | 1px 8px | | --nutui-searchbar-background | 搜索框背景色 | $color-background-sunken |...

(GL_BARBARISM_REPLACE)


[locale-violation] ~127-~127: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...--nutui-searchbar-background | 搜索框背景色 | $color-background-sunken | | --nutui-searchbar-color | ...

(GL_BARBARISM_REPLACE)


[locale-violation] ~129-~129: 'gap' é un xenismo. É preferíbel dicir "hiato"
Context: ...| $color-title | | --nutui-searchbar-gap | 搜索框外部/大间距 | 12px | | --nutui-searc...

(GL_BARBARISM_REPLACE)


[locale-violation] ~130-~130: 'gap' é un xenismo. É preferíbel dicir "hiato"
Context: ...距 | 12px | | --nutui-searchbar-inner-gap | 搜索框内部元素间的间距 | 12px | | --nutui-sea...

(GL_BARBARISM_REPLACE)


[locale-violation] ~132-~132: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...ze-base| | \--nutui-searchbar-content-background | 搜索框中间内容区的背景色 |$color-background-ove...

(GL_BARBARISM_REPLACE)


[locale-violation] ~132-~132: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...bar-content-background | 搜索框中间内容区的背景色 | $color-background-overlay | | --nutui-searchbar-content...

(GL_BARBARISM_REPLACE)


[locale-violation] ~135-~135: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...d模式下的圆角 | 19px | | --nutui-searchbar-input-height | 搜索框输入区高度 | 38px | | --nutui...

(GL_BARBARISM_REPLACE)


[locale-violation] ~136-~136: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...索框输入区高度 | 38px | | --nutui-searchbar-input-padding | 搜索框输入区padding | 0 0 0 8px |...

(GL_BARBARISM_REPLACE)


[duplication] ~136-~136: Posíbel erro tipográfico: hai unha palabra repetida.
Context: ...archbar-input-padding | 搜索框输入区padding | 0 0 0 8px | | --nutui-searchbar-input-tex...

(WORD_REPETITION)

src/packages/searchbar/doc.taro.md

[locale-violation] ~129-~129: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...ing值 | 1px 8px | | --nutui-searchbar-background | 搜索框背景色 | $color-background-sunken |...

(GL_BARBARISM_REPLACE)


[locale-violation] ~129-~129: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...--nutui-searchbar-background | 搜索框背景色 | $color-background-sunken | | --nutui-searchbar-color | ...

(GL_BARBARISM_REPLACE)


[locale-violation] ~131-~131: 'gap' é un xenismo. É preferíbel dicir "hiato"
Context: ...| $color-title | | --nutui-searchbar-gap | 搜索框外部/大间距 | 12px | | --nutui-searc...

(GL_BARBARISM_REPLACE)


[locale-violation] ~132-~132: 'gap' é un xenismo. É preferíbel dicir "hiato"
Context: ...距 | 12px | | --nutui-searchbar-inner-gap | 搜索框内部元素间的间距 | 12px | | --nutui-sea...

(GL_BARBARISM_REPLACE)


[locale-violation] ~134-~134: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...ze-base| | \--nutui-searchbar-content-background | 搜索框中间内容区的背景色 |$color-background-ove...

(GL_BARBARISM_REPLACE)


[locale-violation] ~134-~134: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...bar-content-background | 搜索框中间内容区的背景色 | $color-background-overlay | | --nutui-searchbar-content...

(GL_BARBARISM_REPLACE)


[locale-violation] ~137-~137: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...d模式下的圆角 | 19px | | --nutui-searchbar-input-height | 搜索框输入区高度 | 38px | | --nutui...

(GL_BARBARISM_REPLACE)


[locale-violation] ~138-~138: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...索框输入区高度 | 38px | | --nutui-searchbar-input-padding | 搜索框输入区padding | 0 0 0 8px |...

(GL_BARBARISM_REPLACE)


[duplication] ~138-~138: Posíbel erro tipográfico: hai unha palabra repetida.
Context: ...archbar-input-padding | 搜索框输入区padding | 0 0 0 8px | | --nutui-searchbar-input-tex...

(WORD_REPETITION)

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

[locale-violation] ~129-~129: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...ing值 | 1px 8px | | --nutui-searchbar-background | 搜索框背景色 | $color-background-sunken |...

(GL_BARBARISM_REPLACE)


[locale-violation] ~129-~129: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...--nutui-searchbar-background | 搜索框背景色 | $color-background-sunken | | --nutui-searchbar-color | ...

(GL_BARBARISM_REPLACE)


[locale-violation] ~131-~131: 'gap' é un xenismo. É preferíbel dicir "hiato"
Context: ...| $color-title | | --nutui-searchbar-gap | 搜索框外部/大間距 | 12px | | --nutui-searc...

(GL_BARBARISM_REPLACE)


[locale-violation] ~132-~132: 'gap' é un xenismo. É preferíbel dicir "hiato"
Context: ...距 | 12px | | --nutui-searchbar-inner-gap | 搜索框內部元素間的間距 | 12px | | --nutui-sea...

(GL_BARBARISM_REPLACE)


[locale-violation] ~134-~134: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...ze-base| | \--nutui-searchbar-content-background | 搜索框中間內容區的背景色 |$color-background-ove...

(GL_BARBARISM_REPLACE)


[locale-violation] ~134-~134: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...bar-content-background | 搜索框中間內容區的背景色 | $color-background-overlay | | --nutui-searchbar-content...

(GL_BARBARISM_REPLACE)


[locale-violation] ~137-~137: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...d模式下的圓角 | 19px | | --nutui-searchbar-input-height | 搜索框輸入區高度 | 38px | | --nutui...

(GL_BARBARISM_REPLACE)


[locale-violation] ~138-~138: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...索框輸入區高度 | 38px | | --nutui-searchbar-input-padding | 搜索框輸入區padding | 0 0 0 8px |...

(GL_BARBARISM_REPLACE)


[duplication] ~138-~138: Posíbel erro tipográfico: hai unha palabra repetida.
Context: ...archbar-input-padding | 搜索框輸入區padding | 0 0 0 8px | | --nutui-searchbar-input-tex...

(WORD_REPETITION)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: test
🔇 Additional comments (27)
src/packages/searchbar/demos/taro/demo1.tsx (3)

2-3: 导入了新组件以支持增强的搜索栏功能

代码正确导入了 Divider 组件和图标组件 PhotographScan,这些是展示增强型搜索栏所必需的。


8-19: 搜索栏示例增强,展示了多种配置方式

代码展示了两种搜索栏的实现方式:

  1. 简单搜索栏:带有文本右侧内容
  2. 高级搜索栏:带有左侧扫描图标和复杂的右侧内容(包含拍照图标、分隔线和彩色文本)

这很好地展示了组件的灵活性和自定义能力,与PR的目标一致。


14-17: 右侧内容区域布局良好

右侧区域使用了 flex 布局并正确对齐了元素,添加了点击事件处理器,并使用分隔线和样式化文本增强了视觉效果。

src/packages/searchbar/demo.taro.tsx (3)

15-15: 新增了展示默认值和受控功能的演示组件

这里正确导入了新的演示组件,用于展示 SearchBar 组件的新功能。


21-21: 为新功能添加了多语言支持

代码为新增的"默认值、受控"功能添加了中文简体、中文繁体和英文的翻译,保持了国际化的一致性。

Also applies to: 31-31, 41-41


57-58: 在演示页面中恰当位置添加了新组件

代码在适当位置添加了 Demo10 组件及其标题,使其成为搜索栏演示的一部分,维持了良好的用户体验和功能展示流程。

src/sites/sites-react/doc/docs/taro/migrate-from-v2.md (1)

182-187: 完善了 SearchBar 组件的文档说明

文档清晰地介绍了 SearchBar 组件的新功能:

  1. 明确声明了 value 属性支持受控模式
  2. 新增了 defaultValue 属性,支持以逗号分隔的字符串设置多个默认值
  3. 新增了 onItemClick 属性,用于处理点击默认值项的删除操作

这些文档更新与PR目标一致,为开发者提供了清晰的组件使用指南。

src/packages/searchbar/demos/h5/demo10.tsx (3)

1-4: 导入必要组件和图标

代码正确导入了所需的组件和图标,为演示做好了准备。


6-8: 状态管理设置

为演示受控模式和默认值功能设置了三个状态变量:

  • dvalue:用于管理默认值
  • value:用于第二个搜索栏的受控值
  • value1:用于第一个搜索栏的受控值

状态设计合理,可以演示完整的功能流程。


43-59: 第二个搜索栏展示了基础受控模式

第二个搜索栏展示了:

  1. 基本受控输入
  2. 自动聚焦功能
  3. 更复杂的右侧内容(图标+按钮组合)

实现恰当,提供了不同于第一个搜索栏的使用场景和UI样式。

src/packages/searchbar/doc.zh-TW.md (6)

23-29: 已添加默认值和受控模式的新示例 - 这很好!

新添加的示例展示了SearchBar组件的两个新功能:默认值和受控模式。这能帮助开发者更好地理解如何使用这些新特性。


97-98: 属性描述清晰明确

value属性明确标记为"受控",并添加了新的defaultValue属性,支持通过逗号分割显示多个默认值,这样的文档描述非常清晰。


117-117: 新增事件处理器描述准确

onItemClick事件处理器的描述准确表明了其用途:当用户点击默认值的关闭图标时触发,这与新增的默认值功能相匹配。


128-129: 样式变量更新合理

更新的padding值和背景色变量使搜索框样式更加现代化和一致,符合整体设计风格。

🧰 Tools
🪛 LanguageTool

[locale-violation] ~129-~129: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...ing值 | 1px 8px | | --nutui-searchbar-background | 搜索框背景色 | $color-background-sunken |...

(GL_BARBARISM_REPLACE)


[locale-violation] ~129-~129: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...--nutui-searchbar-background | 搜索框背景色 | $color-background-sunken | | --nutui-searchbar-color | ...

(GL_BARBARISM_REPLACE)


131-132: 新增内部间距变量,优化布局

新增的inner-gap变量有助于统一组件内部元素间的间距,提高了组件布局的一致性。

🧰 Tools
🪛 LanguageTool

[locale-violation] ~131-~131: 'gap' é un xenismo. É preferíbel dicir "hiato"
Context: ...| $color-title | | --nutui-searchbar-gap | 搜索框外部/大間距 | 12px | | --nutui-searc...

(GL_BARBARISM_REPLACE)


[locale-violation] ~132-~132: 'gap' é un xenismo. É preferíbel dicir "hiato"
Context: ...距 | 12px | | --nutui-searchbar-inner-gap | 搜索框內部元素間的間距 | 12px | | --nutui-sea...

(GL_BARBARISM_REPLACE)


135-138: 输入区样式优化合理

圆角、高度和内边距的调整使组件更加美观,同时保持了良好的用户体验。不同模式下(方形/圆形)的圆角差异设置也很合理。

🧰 Tools
🪛 LanguageTool

[locale-violation] ~137-~137: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...d模式下的圓角 | 19px | | --nutui-searchbar-input-height | 搜索框輸入區高度 | 38px | | --nutui...

(GL_BARBARISM_REPLACE)


[locale-violation] ~138-~138: 'input' é un xenismo. É preferíbel dicir "entrada"
Context: ...索框輸入區高度 | 38px | | --nutui-searchbar-input-padding | 搜索框輸入區padding | 0 0 0 8px |...

(GL_BARBARISM_REPLACE)


[duplication] ~138-~138: Posíbel erro tipográfico: hai unha palabra repetida.
Context: ...archbar-input-padding | 搜索框輸入區padding | 0 0 0 8px | | --nutui-searchbar-input-tex...

(WORD_REPETITION)

src/packages/searchbar/doc.taro.md (4)

23-29: 新增默认值和受控模式示例,增强文档完整性

新增的示例部分清晰展示了SearchBar组件的新特性,帮助Taro用户快速理解如何使用这些功能。


97-98: 属性描述准确清晰

明确标注了value为受控属性,并添加了defaultValue属性说明,支持通过逗号分割成多个默认值,文档描述非常准确。


117-117: 事件回调函数描述准确

onItemClick回调函数的描述清晰表达了其功能:当用户点击默认值的关闭按钮时触发,与新增的默认值功能完美配合。


128-129: 样式变量更新合理一致

调整后的样式变量(padding、背景色、间距、圆角、高度等)使组件在Taro环境中呈现出更现代、更一致的外观,提升了用户体验。

Also applies to: 131-132, 135-138

🧰 Tools
🪛 LanguageTool

[locale-violation] ~129-~129: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...ing值 | 1px 8px | | --nutui-searchbar-background | 搜索框背景色 | $color-background-sunken |...

(GL_BARBARISM_REPLACE)


[locale-violation] ~129-~129: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...--nutui-searchbar-background | 搜索框背景色 | $color-background-sunken | | --nutui-searchbar-color | ...

(GL_BARBARISM_REPLACE)

src/packages/searchbar/doc.md (4)

21-27: 新增默认值和受控模式示例,文档更加完善

新增的示例部分有效展示了SearchBar组件的新特性,使开发者能够直观了解如何使用默认值和受控模式功能。


95-96: 属性描述清晰明确

value明确标注为受控属性,并新增defaultValue属性描述,支持通过逗号分割成多个默认值,文档表述准确清晰。


115-115: 事件处理器描述准确

onItemClick事件处理器的描述清晰表明了其用途:当用户点击默认值项的关闭图标时触发,与新增的默认值功能逻辑一致。


126-130: 样式变量更新合理

对各种样式变量(padding、背景色、间距、圆角、高度等)的调整使组件呈现出更现代、更一致的外观,同时保持了良好的用户体验。

Also applies to: 133-136

🧰 Tools
🪛 LanguageTool

[locale-violation] ~127-~127: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...ing值 | 1px 8px | | --nutui-searchbar-background | 搜索框背景色 | $color-background-sunken |...

(GL_BARBARISM_REPLACE)


[locale-violation] ~127-~127: 'background' é un xenismo. É preferíbel dicir "formación de base"
Context: ...--nutui-searchbar-background | 搜索框背景色 | $color-background-sunken | | --nutui-searchbar-color | ...

(GL_BARBARISM_REPLACE)


[locale-violation] ~129-~129: 'gap' é un xenismo. É preferíbel dicir "hiato"
Context: ...| $color-title | | --nutui-searchbar-gap | 搜索框外部/大间距 | 12px | | --nutui-searc...

(GL_BARBARISM_REPLACE)


[locale-violation] ~130-~130: 'gap' é un xenismo. É preferíbel dicir "hiato"
Context: ...距 | 12px | | --nutui-searchbar-inner-gap | 搜索框内部元素间的间距 | 12px | | --nutui-sea...

(GL_BARBARISM_REPLACE)

src/packages/searchbar/demos/taro/demo10.tsx (3)

1-9: 状态管理设计合理

组件使用了三个状态变量来管理不同场景:dvalue用于默认值,valuevalue1用于受控输入,这种设计清晰展示了组件的两种使用模式。


11-32: 默认值处理逻辑完善

第一个SearchBar组件展示了defaultValueonItemClick的使用方式。当焦点进入搜索框时,将默认值转移到受控值中并清空默认值,这是一种合理的交互设计。

onItemClick的实现也很完善,能够正确从默认值列表中移除被点击的项,并更新状态。


43-59: 受控组件示例实现良好

第二个SearchBar组件展示了受控模式的使用,autoFocus属性和右侧搜索按钮的组合提供了良好的用户体验。右侧内容的样式设置也很合理,使用flex布局使元素垂直居中对齐。

Comment on lines 186 to 190
const clearaVal = (event: MouseEvent<HTMLDivElement>) => {
if (disabled || readOnly) {
return
}
if (disabled || readOnly) return
setValue('')
onChange && onChange?.('')
onChange && onChange('')
onClear && onClear(event)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

🚨 clearaVal 调用 onChange 参数缺失
onChange 在其他位置期望 (value, event) 两个参数,这里仅传递了 '',会造成类型不一致或信息丢失。

- onChange && onChange('')
+ onChange?.('', event)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const clearaVal = (event: MouseEvent<HTMLDivElement>) => {
if (disabled || readOnly) {
return
}
if (disabled || readOnly) return
setValue('')
onChange && onChange?.('')
onChange && onChange('')
onClear && onClear(event)
const clearaVal = (event: MouseEvent<HTMLDivElement>) => {
if (disabled || readOnly) return
setValue('')
onChange?.('', event)
onClear && onClear(event)
}
🧰 Tools
🪛 Biome (1.9.4)

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

Comment on lines 194 to 198
if (disabled || readOnly) return
setValue('')
forceFocus()
onChange && onChange?.('')
onChange && onChange('')
onClear && onClear(event)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

🚨 清空回调参数不完整
仅向 onChange 传入空字符串,遗漏事件对象。

- onChange && onChange('')
+ onChange?.('', event)
🧰 Tools
🪛 Biome (1.9.4)

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

@codecov
Copy link

codecov bot commented Apr 29, 2025

Codecov Report

Attention: Patch coverage is 87.83784% with 18 lines in your changes missing coverage. Please review.

Project coverage is 86.62%. Comparing base (bc1f644) to head (5833294).
Report is 8 commits behind head on feat_v3.x.

Files with missing lines Patch % Lines
src/packages/searchbar/searchbar.tsx 87.83% 18 Missing ⚠️
Additional details and impacted files
@@              Coverage Diff              @@
##           feat_v3.x    #3209      +/-   ##
=============================================
+ Coverage      86.54%   86.62%   +0.08%     
=============================================
  Files            289      289              
  Lines          18739    18807      +68     
  Branches        2822     2830       +8     
=============================================
+ Hits           16217    16292      +75     
+ Misses          2517     2510       -7     
  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

♻️ Duplicate comments (3)
src/packages/searchbar/searchbar.tsx (3)

71-73: ⚠️ Potential issue

defaultValue 同步逻辑需要优化以避免破坏受控模式

当前的 useEffect 在 defaultValue 变化时无条件调用 setValue(defaultValue),会导致组件处于受控(传入 value)时被意外覆盖。

-useEffect(() => {
-  setValue(defaultValue)
-}, [defaultValue])
+useEffect(() => {
+  // 仅在组件非受控且 defaultValue 有效时同步内部状态
+  if (outerValue === undefined && defaultValue !== undefined) {
+    setValue(defaultValue)
+  }
+}, [defaultValue, outerValue])

120-136: ⚠️ Potential issue

onItemClick 调用需做可选链保护

当前直接调用 onItemClick(item),当父组件未传该回调时会抛出运行时异常。

-onClick={() => onItemClick(item)}
+onClick={() => onItemClick?.(item)}

187-191: ⚠️ Potential issue

clearaVal 调用 onChange 参数缺失

onChange 在其他位置期望接收 (value, event) 两个参数,这里仅传递了空字符串,会导致类型不一致或信息丢失。

-onChange && onChange('')
+onChange?.('', event)
🧰 Tools
🪛 Biome (1.9.4)

[error] 190-191: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🧹 Nitpick comments (3)
src/packages/searchbar/searchbar.tsx (3)

80-84: handleChange 函数可以使用可选链

使用可选链可以使代码更简洁并避免潜在的错误。

-onChange && onChange(value, event)
+onChange?.(value, event)
🧰 Tools
🪛 Biome (1.9.4)

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


87-87: handleFocus 函数使用冗余的可选链

event?.target?.value 中使用了多个可选链,但上下文中 event 一定存在,可以简化。

-onFocus && onFocus(event?.target?.value, event)
+onFocus?.(event.target.value, event)
🧰 Tools
🪛 Biome (1.9.4)

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


92-94: handleBlur 函数也有类似问题

同上,可以简化可选链的使用。

-searchSelf && searchSelf.blur()
-onBlur && onBlur(event?.target?.value, event)
+searchSelf?.blur()
+onBlur?.(event.target.value, event)
🧰 Tools
🪛 Biome (1.9.4)

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 93-93: 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 f174e0d and ec8d87f.

📒 Files selected for processing (2)
  • src/packages/searchbar/__tests__/searchbar.spec.tsx (1 hunks)
  • src/packages/searchbar/searchbar.tsx (7 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
src/packages/searchbar/searchbar.tsx

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: test
🔇 Additional comments (6)
src/packages/searchbar/__tests__/searchbar.spec.tsx (3)

29-33: 测试用例覆盖了新增的默认值功能

测试用例正确验证了新增的 defaultValue 属性,确保组件能够正确渲染默认值标签。


35-42: rightIn 属性测试完善

测试用例很好地覆盖了 rightIn 属性的两种使用场景:字符串和 React 元素。这与组件实现中对 rightIn 渲染逻辑的增强相匹配。


44-89: 事件处理测试完善且全面

该测试用例全面覆盖了组件的各种交互场景,包括受控输入、焦点变化、按钮点击等。使用 waitFor 确保异步状态更新后的断言有效。

使用 Demo 组件模拟受控场景的测试方法非常合适,能够真实反映用户使用场景。

src/packages/searchbar/searchbar.tsx (3)

65-69: 使用 usePropsValue 增强受控与非受控逻辑

使用 usePropsValue 代替原有的 useState 是个很好的改进,这样能够更好地处理受控与非受控组件场景。


155-167: renderRightIn 函数优化合理

使用 React.isValidElement 检查是合理的,这样可以根据不同类型的 rightIn 提供适当的渲染方式。


224-226: 条件渲染逻辑清晰优化

根据是否存在 defaultValue 决定是否显示清除按钮的逻辑非常合理。只在没有默认值且有输入内容时才显示清除按钮,可以避免界面元素过多造成混乱。

})

useEffect(() => {
setValue(defaultValue)
Copy link
Collaborator

Choose a reason for hiding this comment

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

defaultValue一般作为非受控的属性名,这里似乎不应该监听defaultValue的变化来更新状态

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

原定于通过默认值控制,后增加 tag 标识处理。已fixed


useEffect(() => {
setValue(defaultValue)
}, [defaultValue])
Copy link
Collaborator

Choose a reason for hiding this comment

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

这里看上去不应该使用

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

原定于通过默认值控制,后增加 tag 标识处理。已fixed

@oasis-cloud
Copy link
Collaborator

带 tag 的搜索框,获得焦点的时候,把分割符号去掉?

@oasis-cloud
Copy link
Collaborator

更多选项无法展开

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

♻️ Duplicate comments (2)
src/packages/searchbar/searchbar.tsx (1)

183-189: ⚠️ Potential issue

问题:clearaValonChange 调用参数缺失

在清空输入框时,onChange 回调只传递了空字符串,但缺少了事件对象,这与其他地方的调用模式不一致。

-    onChange && onChange('')
+    onChange?.('', event)
🧰 Tools
🪛 Biome (1.9.4)

[error] 186-187: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 187-188: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

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

193-193: ⚠️ Potential issue

问题:clearaValonChange 调用参数缺失

onChange 回调在其他地方传递了两个参数(值和事件),但这里只传递了空字符串,导致参数不一致。

-    onChange && onChange('')
+    onChange?.('', event)
🧰 Tools
🪛 Biome (1.9.4)

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🧹 Nitpick comments (7)
src/packages/searchbar/searchbar.tsx (4)

76-80: 建议:使用可选链操作符

当前的回调调用方式存在潜在风险,当 onChange 未定义时可能导致错误。

-    onChange && onChange(value, event)
+    onChange?.(value, event)
🧰 Tools
🪛 Biome (1.9.4)

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


83-83: 建议:使用可选链操作符简化访问

使用可选链操作符可以简化条件检查逻辑。

-    onFocus && onFocus(event?.target?.value, event)
+    onFocus?.(event?.target?.value, event)
🧰 Tools
🪛 Biome (1.9.4)

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


89-89: 建议:使用可选链操作符

与前面类似,使用可选链操作符提高代码健壮性。

-    onBlur && onBlur(event?.target?.value, event)
+    onBlur?.(event?.target?.value, event)
🧰 Tools
🪛 Biome (1.9.4)

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


175-175: 问题:clearaVal 事件处理函数需要类型

onClick={clearaVal} 直接传递函数而不指定事件参数,可能会导致类型不匹配的问题。

-        onClick={clearaVal}
+        onClick={(event) => clearaVal(event)}
src/packages/searchbar/searchbar.taro.tsx (3)

85-85: 建议:使用可选链操作符

处理回调时应使用可选链以提高代码健壮性。

-    onChange && onChange(eventValue, event)
+    onChange?.(eventValue, event)
🧰 Tools
🪛 Biome (1.9.4)

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


92-92: 建议:使用可选链操作符

同样,处理 onFocus 回调时也应使用可选链。

-    onFocus && onFocus(event?.detail?.value, event)
+    onFocus?.(event?.detail?.value, event)
🧰 Tools
🪛 Biome (1.9.4)

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


99-99: 建议:使用可选链操作符

处理 onBlur 回调时也应使用可选链。

-    onBlur && onBlur(event?.detail?.value, event)
+    onBlur?.(event?.detail?.value, event)
🧰 Tools
🪛 Biome (1.9.4)

[error] 99-99: 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 94d1c43 and 77ba15b.

📒 Files selected for processing (2)
  • src/packages/searchbar/searchbar.taro.tsx (5 hunks)
  • src/packages/searchbar/searchbar.tsx (7 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
src/packages/searchbar/searchbar.tsx (2)
src/hooks/use-props-value.ts (1)
  • usePropsValue (11-35)
src/packages/calendarcard/icon.taro.tsx (1)
  • ArrowLeft (44-44)
src/packages/searchbar/searchbar.taro.tsx (2)
src/hooks/use-props-value.ts (1)
  • usePropsValue (11-35)
src/packages/calendarcard/icon.taro.tsx (1)
  • ArrowLeft (44-44)
🪛 Biome (1.9.4)
src/packages/searchbar/searchbar.tsx

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

src/packages/searchbar/searchbar.taro.tsx

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

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

65-69: 改进:使用 usePropsValue 提升组件状态管理

通过引入 usePropsValue 钩子替代原有的 useState,大幅提升了组件的受控和非受控模式兼容性。这种方式能够自动处理 valuedefaultValue 之间的关系,使组件更加符合 React 最佳实践。


116-132: 很好的实现:默认值标签展示功能

新增的默认值展示功能实现得很好,提供了清晰的用户界面元素来显示和管理默认值。特别是:

  1. 使用逗号分隔多个默认值
  2. 为每个标签添加关闭图标
  3. 实现了点击删除功能

在实际应用中,这个功能可以提供更好的搜索体验。


124-124: 问题:onItemClick 回调需要可选链保护

onItemClick 未定义时,当前的直接调用方式会导致运行时错误。

-            onClick={() => onItemClick?.(item)}
+            onClick={() => onItemClick?.(item)}

这里已经使用了可选链,很好。这样既保持类型提示,又确保在非受控场景下组件稳定运行。


154-162: 改进:优化右侧元素渲染逻辑

根据元素类型渲染不同的结构是一个很好的改进,这使得组件更加灵活,能够处理更多类型的右侧内容。使用 React.isValidElement 检查是正确且安全的方法。


220-222: 改进:条件渲染清除按钮

根据 defaultValuevalue 状态条件渲染清除按钮的逻辑很好,这确保了用户界面的一致性。当有默认值标签显示时,不显示清除按钮是合理的设计决策。

src/packages/searchbar/searchbar.taro.tsx (4)

72-76: 改进:使用 usePropsValue 提升组件受控性

使用 usePropsValue 取代原有的状态管理方式,统一了组件的受控和非受控行为,使其更符合 React 组件设计规范,同时提高了代码一致性。


128-144: 很好的实现:默认值标签展示功能

新增的默认值展示功能实现得很好,包括:

  1. 正确使用了 Taro 的 View 组件
  2. 为每个标签提供了独特的 key
  3. 实现点击回调使用了可选链,确保安全

这个功能对于提升用户体验非常有价值,允许用户看到并管理默认搜索值。


164-173: 改进:优化右侧元素渲染逻辑

对右侧元素的条件渲染处理得很好,使用 React.isValidElement 判断是否需要添加图标类名是正确的实现方式。这提高了组件的灵活性和可扩展性。


217-222: 改进:优化输入框和默认值的布局结构

将输入框和默认值标签包装在专门的容器中是个很好的设计决定,这将使布局更加灵活,也便于应用样式。条件渲染清除按钮的逻辑与 React 版本保持一致,确保了组件行为的一致性。

@xiaoyatong xiaoyatong requested a review from oasis-cloud May 1, 2025 15:57
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: 4

♻️ Duplicate comments (5)
src/packages/searchbar/searchbar.taro.tsx (1)

126-135: ⚠️ Potential issue

修正 clearaValonChange 回调参数不完整

当清空输入框时,只向 onChange 传递了空字符串,而没有传递事件对象,这与组件其他地方调用 onChange(value, event) 的模式不一致。

-onChange && onChange('')
+onChange?.('', event)

保持参数一致性有助于使用方更可预测地处理事件。

🧰 Tools
🪛 Biome (1.9.4)

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

src/packages/searchbar/searchbar.tsx (4)

181-204: 优化标签渲染逻辑

  1. 渲染标签列表时使用了索引作为 key,这在列表项重新排序时可能导致不必要的重渲染或状态错误。建议使用更稳定的唯一标识。

  2. 使用了 setTimeout 但没有清理逻辑,可能导致内存泄漏。

 const renderValueByTags = useCallback(() => {
   if (!value) {
-    setTimeout(() => {
+    // 避免使用 setTimeout,可以直接调用
+    requestAnimationFrame(() => {
       forceFocus()
-    }, 0)
     })
     return null
   }
   const list = value.split(',')
   if (!list) return null
   return (
     <div className="nut-searchbar-values">
       {list.map((item, index) => (
         <div
-          key={`def-${index}`}
+          key={`${item}-${index}`}
           className="nut-searchbar-value"
           onClick={(e) => onItemClick?.(item, e)}
         >
           {item}
           <Close />
         </div>
       ))}
     </div>
   )
 }, [value, onItemClick])
🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 183-187: src/packages/searchbar/searchbar.tsx#L183-L187
Added lines #L183 - L187 were not covered by tests


250-250: 使用 locale 系统进行国际化

"清除"文本被硬编码为中文,建议使用 locale 系统以支持国际化。

-aria-label="清除"
+aria-label={locale.clear || "清除"}

同时建议在 locale 配置中添加对应的翻译项。


119-128: ⚠️ Potential issue

修正 clearaValonChange 回调参数不完整

当清空输入框时,只向 onChange 传递了空字符串,而没有传递事件对象,这与组件其他地方调用 onChange(value, event) 的模式不一致。

-onChange && onChange('')
+onChange?.('', event)

保持参数一致性有助于使用方更可预测地处理事件。

🧰 Tools
🪛 Biome (1.9.4)

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


109-118: 🛠️ Refactor suggestion

处理 setTimeout 可能导致的内存泄漏

handleBlur 中使用了 setTimeout 但未在组件卸载时清除,这可能导致内存泄漏。建议使用 useEffect 清理定时器。

+const [blurTimer, setBlurTimer] = useState<NodeJS.Timeout | null>(null)

 const handleBlur = useCallback(
   (event: FocusEvent<HTMLInputElement>) => {
     searchInputRef.current?.blur()
     onBlur && onBlur(event.target?.value, event)
-    setTimeout(() => {
+    const timer = setTimeout(() => {
       setInnerTag(event.target?.value ? tag : false)
     }, 150)
+    setBlurTimer(timer)
   },
   [onBlur, tag, value]
 )

+useEffect(() => {
+  return () => {
+    if (blurTimer) clearTimeout(blurTimer)
+  }
+}, [blurTimer])
🧰 Tools
🪛 Biome (1.9.4)

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🪛 GitHub Check: codecov/patch

[warning] 114-114: src/packages/searchbar/searchbar.tsx#L114
Added line #L114 was not covered by tests

🧹 Nitpick comments (9)
src/packages/searchbar/demos/taro/demo10.tsx (1)

37-53: 移除注释代码

这段被注释的代码似乎是未完成或废弃的功能。如果不需要,建议完全移除;如果是计划中的功能,应该添加TODO注释说明用途。

-{/* <SearchBar
-  backable
-  leftIn={null}
-  value={value}
-  onChange={(val) => {
-    setValue(val)
-  }}
-  // autoFocus
-  rightIn={
-    <div style={{ display: 'flex', alignItems: 'center' }}>
-      <Photograph color="#505259" style={{ marginRight: '12px' }} />
-      <Button type="primary" size="mini">
-        搜索
-      </Button>
-    </div>
-  }
-/> */}
src/packages/searchbar/__tests__/searchbar.spec.tsx (1)

44-89: 全面的事件处理测试

这个测试用例很全面,通过创建一个完整的Demo组件来模拟真实使用场景,测试了所有主要事件和状态更新。使用 waitFor 处理异步状态更新很合理。

建议添加对 onItemClick 回调的测试,因为这是新增的重要功能。

test('should handle all events correctly', async () => {
  const handleChange = vi.fn()
  const handleFocus = vi.fn()
  const handleBlur = vi.fn()
  const handleClick = vi.fn()
  const handleClear = vi.fn()
+ const handleItemClick = vi.fn()
  const Demo = () => {
    const [value, setValue] = useState('奶茶')
    const onChange = (newValue: string) => {
      setValue(newValue) // 更新状态
      handleChange(newValue) // 调用传入的 onChange 处理函数
    }
    return (
      <SearchBar
        value={value}
        autoFocus
+       tag
        onChange={onChange}
        onFocus={handleFocus}
        onBlur={handleBlur}
        onInputClick={handleClick}
        onClear={handleClear}
+       onItemClick={handleItemClick}
      />
    )
  }

  const { container } = render(<Demo />)
  
  // 现有测试代码...
  
+ // 测试标签点击
+ if (container.querySelector('.nut-searchbar-value')) {
+   const tag = container.querySelector('.nut-searchbar-value') as Element
+   fireEvent.click(tag)
+   expect(handleItemClick).toHaveBeenCalledTimes(1)
+ }
src/packages/searchbar/searchbar.taro.tsx (5)

96-96: 使用可选链操作符增强代码健壮性

建议在调用回调函数时使用可选链操作符,这样即使回调未定义也不会抛出错误。

-onChange && onChange(eventValue, event)
+onChange?.(eventValue, event)

其他几处相同模式的回调也应同时修改 (105, 114, 131, 132, 286行)。

🧰 Tools
🪛 Biome (1.9.4)

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


206-230: 优化标签渲染逻辑

  1. 渲染标签列表时使用了索引作为 key,这在列表项重新排序时可能导致不必要的重渲染或状态错误。建议使用更稳定的唯一标识。

  2. 使用了 setTimeout 但没有清理逻辑,可能导致内存泄漏。

  3. 在用户点击标签时,建议提供更明确的视觉或焦点反馈。

 const renderValueByTags = useCallback(() => {
   if (!innerTag) return null
   if (!value) {
-    setTimeout(() => {
+    // 避免使用 setTimeout,可以直接调用
+    requestAnimationFrame(() => {
       forceFocus()
-    }, 0)
     })
     return null
   }
   const list = value.split(',')
   if (!list) return null
   return (
     <View className="nut-searchbar-values">
       {list.map((item, index) => (
         <View
-          key={`def-${index}`}
+          key={`${item}-${index}`}
           className="nut-searchbar-value"
           onClick={(e) => onItemClick?.(item, e)}
         >
           {item}
           <Close />
         </View>
       ))}
     </View>
   )
 }, [value, onItemClick, innerTag])

163-201: 考虑简化环境判断逻辑

当前代码中WEB环境和非WEB环境有大量重复代码,只有 focus/autoFocus 属性不同。建议提取共同部分减少冗余。

 const renderField = () => {
   const inputCls = classNames(`${classPrefix}-input`)
+  const commonProps = {
+    className: inputCls,
+    ref: searchInputRef,
+    style: {
+      ...style,
+      ...{ color: `${innerTag ? 'transparent' : '#333'}` },
+    },
+    value,
+    placeholder: placeholder || locale.placeholder,
+    disabled: disabled || readOnly,
+    maxlength: maxLength,
+    onInput: handleInput,
+    onFocus: handleFocus,
+    onBlur: handleBlur,
+    onClick: onInputClick,
+    onConfirm: onConfirm,
+  }
+  
   return (
     <>
       {Taro.getEnv() === 'WEB' ? (
-        <TaroInput
-          className={inputCls}
-          ref={searchInputRef}
-          style={{
-            ...style,
-            ...{ color: `${innerTag ? 'transparent' : '#333'}` },
-          }}
-          value={value}
-          placeholder={placeholder || locale.placeholder}
-          disabled={disabled || readOnly}
-          maxlength={maxLength}
-          autoFocus={autoFocus}
-          onInput={handleInput}
-          onFocus={handleFocus}
-          onBlur={handleBlur}
-          onClick={onInputClick}
-          onConfirm={onConfirm}
-        />
+        <TaroInput {...commonProps} autoFocus={autoFocus} />
       ) : (
-        <TaroInput
-          className={inputCls}
-          ref={searchInputRef}
-          style={{
-            ...style,
-            ...{ color: `${innerTag ? 'transparent' : '#333'}` },
-          }}
-          value={value}
-          placeholder={placeholder || locale.placeholder}
-          disabled={disabled || readOnly}
-          maxlength={maxLength}
-          focus={autoFocus}
-          onInput={handleInput}
-          onFocus={handleFocus}
-          onBlur={handleBlur}
-          onClick={onInputClick}
-          onConfirm={onConfirm}
-        />
+        <TaroInput {...commonProps} focus={autoFocus} />
       )}
     </>
   )
 }

270-283: 优化清除按钮逻辑

当前清除按钮通过 CSS 的 visibility 属性来控制显示/隐藏,但这仍会在 DOM 中保留元素。考虑使用条件渲染来提高性能,尤其是在低端设备上。

 const renderClear = useCallback(() => {
+  if (!value || !clearable || innerTag) return null
   return (
     <View
       className={`${classPrefix}-clear ${classPrefix}-icon`}
-      style={{
-        visibility: `${!innerTag && value && clearable ? 'visible' : 'hidden'}`,
-      }}
       onClick={clearaVal}
       aria-label="清除"
     >
       <MaskClose />
     </View>
   )
 }, [value, clearable, clearaVal, innerTag])

278-278: 使用 locale 系统进行国际化

"清除"文本被硬编码为中文,建议使用 locale 系统以支持国际化。

-aria-label="清除"
+aria-label={locale.clear || "清除"}

同时建议在 locale 配置中添加对应的翻译项。

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

88-91: 使用可选链操作符增强代码健壮性

建议在调用回调函数时使用可选链操作符,这样即使回调未定义也不会抛出错误。

-onChange && onChange(value, event)
+onChange?.(value, event)

其他几处相同模式的回调也应同时修改 (103, 112, 124, 125, 137行)。

🧰 Tools
🪛 Biome (1.9.4)

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


244-255: renderClear 方法与 Taro 版本实现不一致

Web 版本中 renderClear 实现与 Taro 版本不同:Web 版本在条件不满足时返回 null,而 Taro 版本则使用 CSS visibility 控制显示隐藏。这种不一致可能导致行为差异。

建议统一两个版本的行为模式,都采用条件渲染的方式:

 const renderClear = useCallback(() => {
-  if (!value || !clearable) return null
+  if (!value || !clearable || innerTag) return null
   return (
     <div
       className={`${classPrefix}-clear ${classPrefix}-icon`}
       onClick={clearaVal}
       aria-label="清除"
     >
       <MaskClose />
     </div>
   )
 }, [value, clearable, clearaVal])
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 77ba15b and 1937622.

📒 Files selected for processing (10)
  • scripts/harmony/update-taro-entry.js (2 hunks)
  • src/packages/searchbar/__tests__/searchbar.spec.tsx (1 hunks)
  • src/packages/searchbar/demos/h5/demo10.tsx (1 hunks)
  • src/packages/searchbar/demos/taro/demo1.tsx (1 hunks)
  • src/packages/searchbar/demos/taro/demo10.tsx (1 hunks)
  • src/packages/searchbar/demos/taro/demo5.tsx (1 hunks)
  • src/packages/searchbar/searchbar.scss (2 hunks)
  • src/packages/searchbar/searchbar.taro.tsx (4 hunks)
  • src/packages/searchbar/searchbar.tsx (4 hunks)
  • src/types/spec/searchbar/base.ts (2 hunks)
✅ Files skipped from review due to trivial changes (1)
  • src/packages/searchbar/demos/taro/demo5.tsx
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/packages/searchbar/demos/h5/demo10.tsx
  • src/packages/searchbar/demos/taro/demo1.tsx
  • src/packages/searchbar/searchbar.scss
🧰 Additional context used
🧬 Code Graph Analysis (3)
scripts/harmony/update-taro-entry.js (3)
scripts/taro/generate-taro-route.js (2)
  • configRef (9-9)
  • config (2-2)
scripts/taro/generate-taro-pages.js (1)
  • config (4-4)
scripts/create-component-mode.js (1)
  • config (5-5)
src/packages/searchbar/__tests__/searchbar.spec.tsx (1)
src/packages/searchbar/searchbar.tsx (1)
  • SearchBar (33-273)
src/packages/searchbar/demos/taro/demo10.tsx (1)
src/packages/searchbar/searchbar.taro.tsx (1)
  • SearchBar (40-306)
🪛 Biome (1.9.4)
src/packages/searchbar/searchbar.tsx

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

src/packages/searchbar/searchbar.taro.tsx

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 286-287: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

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

[warning] 114-114: src/packages/searchbar/searchbar.tsx#L114
Added line #L114 was not covered by tests


[warning] 132-139: src/packages/searchbar/searchbar.tsx#L132-L139
Added lines #L132 - L139 were not covered by tests


[warning] 183-187: src/packages/searchbar/searchbar.tsx#L183-L187
Added lines #L183 - L187 were not covered by tests

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: test
🔇 Additional comments (8)
scripts/harmony/update-taro-entry.js (2)

24-24: 变量定义类型的调整

configRefconst 改为 let 是为了支持后续的过滤操作,这个变更是必要的,逻辑清晰。


52-54: 优化了导航配置的处理逻辑

添加过滤空页面数组的逻辑很合理,这样可以避免在生成的配置中包含没有实际页面的导航项,提高了代码的健壮性。

src/types/spec/searchbar/base.ts (3)

7-7: 增加默认值属性,支持非受控模式

添加 defaultValue 属性很好地支持了非受控组件模式,使组件更加灵活。这与 React 的设计理念一致。


20-20: 新增标签展示模式

tag 属性的添加使搜索框支持标签显示模式,增强了组件的展示能力,对于多值输入场景非常有用。


27-27: 添加标签点击事件回调

onItemClick 回调函数的添加完善了标签交互功能,允许开发者自定义处理标签点击事件,增强了组件的可控性。

src/packages/searchbar/demos/taro/demo10.tsx (1)

5-8: 示例组件状态管理

组件状态设置合理,使用了 useState 创建了两个状态变量:一个用于普通值,一个用于逗号分隔的多值。

src/packages/searchbar/__tests__/searchbar.spec.tsx (2)

29-33: 添加标签渲染测试

很好地测试了标签渲染功能,验证了传入逗号分隔的值时能正确显示为多个标签。


35-42: 增加了右侧内容测试

测试了 rightIn 属性的两种用法:字符串和React节点,覆盖了主要使用场景。

Comment on lines +10 to +36
<SearchBar
backable
leftIn={null}
value={value1}
tag
onItemClick={(val: string) => {
console.log('click', val)
const arr = value1.split(',')
const newArr = arr.filter((item: string) => item !== val)
const newVal = newArr.length > 1 ? newArr.join(',') : newArr.join('')
setValue1(newVal)
}}
onFocus={(val: string) => {
console.log('focus value', val)
setValue1(val.split(',').join(''))
}}
onChange={(val) => {
console.log('onChange', val)
setValue1(val)
}}
rightIn={
<div style={{ display: 'flex', alignItems: 'center' }}>
<Photograph color="#505259" />
</div>
}
right={<Category />}
/>
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

完善标签删除逻辑

标签点击处理逻辑符合预期,但可以进一步优化数组处理和状态更新:

  1. 当用户点击标签时,在失去焦点后应该重新展示为标签格式
  2. 根据PR评论,当搜索框获取焦点时,标签之间的分隔符应被移除
onFocus={(val: string) => {
  console.log('focus value', val)
  setValue1(val.split(',').join(''))
}}
onBlur={(val: string) => {
+  // 在失去焦点时,如果输入内容包含多个项目,重新格式化为逗号分隔
+  if (val && !val.includes(',') && val.trim() !== '') {
+    const items = val.split(/\s+/).filter(item => item.trim() !== '');
+    if (items.length > 1) {
+      setValue1(items.join(','));
+      return;
+    }
+  }
+  setValue1(val);
}}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<SearchBar
backable
leftIn={null}
value={value1}
tag
onItemClick={(val: string) => {
console.log('click', val)
const arr = value1.split(',')
const newArr = arr.filter((item: string) => item !== val)
const newVal = newArr.length > 1 ? newArr.join(',') : newArr.join('')
setValue1(newVal)
}}
onFocus={(val: string) => {
console.log('focus value', val)
setValue1(val.split(',').join(''))
}}
onChange={(val) => {
console.log('onChange', val)
setValue1(val)
}}
rightIn={
<div style={{ display: 'flex', alignItems: 'center' }}>
<Photograph color="#505259" />
</div>
}
right={<Category />}
/>
<SearchBar
backable
leftIn={null}
value={value1}
tag
onItemClick={(val: string) => {
console.log('click', val)
const arr = value1.split(',')
const newArr = arr.filter((item: string) => item !== val)
const newVal = newArr.length > 1 ? newArr.join(',') : newArr.join('')
setValue1(newVal)
}}
onFocus={(val: string) => {
console.log('focus value', val)
setValue1(val.split(',').join(''))
}}
onBlur={(val: string) => {
// 在失去焦点时,如果输入内容包含多个项目,重新格式化为逗号分隔
if (val && !val.includes(',') && val.trim() !== '') {
const items = val.split(/\s+/).filter(item => item.trim() !== '');
if (items.length > 1) {
setValue1(items.join(','));
return;
}
}
setValue1(val);
}}
onChange={(val) => {
console.log('onChange', val)
setValue1(val)
}}
rightIn={
<div style={{ display: 'flex', alignItems: 'center' }}>
<Photograph color="#505259" />
</div>
}
right={<Category />}
/>

{renderField()}
{clearable && !value && renderRightIn()}
{clearable && value && handleClear()}
{innerTag ? renderValueByTags() : renderClear()}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

处理标签渲染和清除按钮的条件逻辑不一致

Web 版本使用 {innerTag ? renderValueByTags() : renderClear()} 表示只会渲染标签或清除按钮中的一个,而 Taro 版本中这两个元素是分开渲染的,可能同时显示。这种不一致可能导致用户体验差异。

-{innerTag ? renderValueByTags() : renderClear()}
+{innerTag && renderValueByTags()}
+{!innerTag && renderClear()}

或者使用与 Taro 版本一致的实现:

-{innerTag ? renderValueByTags() : renderClear()}
+{renderValueByTags()}
+{renderClear()}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{innerTag ? renderValueByTags() : renderClear()}
- {innerTag ? renderValueByTags() : renderClear()}
+ {innerTag && renderValueByTags()}
+ {!innerTag && renderClear()}

Comment on lines +131 to +141
(e: React.KeyboardEvent) => {
if (e.key === 'Enter') {
const event = e.nativeEvent
if (typeof event.cancelable !== 'boolean' || event.cancelable) {
event.preventDefault()
}
onSearch && onSearch(value as string)
}
},
[onSearch, value]
)
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

增加键盘事件处理的测试覆盖

静态分析工具报告这段代码未被测试覆盖。建议添加相应的单元测试,确保键盘事件的处理逻辑按预期工作。

可测试以下情况:

  1. 按下 Enter 键时触发搜索回调
  2. 事件preventDefault 被正确调用
  3. 不同键的不同行为

🏁 Script executed:

#!/bin/bash
# 检查是否有对应的键盘事件测试
grep -r "onKeyDown\|press.*Enter\|key.*event" src/packages/searchbar/__tests__

Length of output: 80


我们可以进一步确认是否已为 SearchBar 的键盘事件添加测试,运行以下脚本:

请求确认运行结果,以决定是否需要新增键盘事件处理的单元测试覆盖。


🏁 Script executed:

#!/bin/bash
# 列出 src/packages/searchbar 目录下所有测试文件
test_files=$(find src/packages/searchbar -type f | grep -E "(__tests__|\\.test\\.(js|ts|tsx))")
if [ -z "$test_files" ]; then
  echo "未找到 searchbar 的测试文件"
  exit 0
fi
echo "找到以下测试文件:"
echo "$test_files"
echo "—— 在这些文件中搜索 'Enter' 相关测试 ——"
grep -R "Enter" $test_files || echo "在测试文件中未找到与 'Enter' 相关的测试"

Length of output: 657


请为 SearchBar 组件的键盘事件处理补充单元测试

在当前的 src/packages/searchbar/__tests__/searchbar.spec.tsx 中,未发现对 Enter 键处理逻辑的测试覆盖。建议新增以下测试用例,确保键盘事件行为符合预期:

  • 按下 Enter 键时,应调用 onSearch 回调
  • 按下 Enter 键时,应正确调用 event.preventDefault()
  • 按下其他键(如 Esc、空格等)时,不应触发 onSearch

请在上述测试文件中添加相应覆盖。

🧰 Tools
🪛 Biome (1.9.4)

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🪛 GitHub Check: codecov/patch

[warning] 132-139: src/packages/searchbar/searchbar.tsx#L132-L139
Added lines #L132 - L139 were not covered by tests

@irisSong
Copy link
Collaborator

irisSong commented May 2, 2025

image 点击popover没有展示 页面有遮罩卡住了

@irisSong
Copy link
Collaborator

irisSong commented May 2, 2025

1、清除按钮扩大点击区,移除占位 2、文字居又展示右侧空白太大

@xiaoyatong
Copy link
Collaborator Author

1、清除按钮扩大点击区,移除占位 2、文字居又展示右侧空白太大

done

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: 3

♻️ Duplicate comments (4)
src/packages/searchbar/demos/taro/demo10.tsx (1)

22-25: 🛠️ Refactor suggestion

考虑添加onBlur事件处理

组件在获取焦点时将逗号分隔的字符串转换为无分隔符的形式,但缺少相应的onBlur处理逻辑来恢复其显示。根据PR评论,当搜索框获取焦点时标签之间的分隔符应被移除,失去焦点后应恢复。

onFocus={(val: string) => {
  console.log('focus value', val)
  setValue1(val.split(',').join(''))
}}
+onBlur={(val: string) => {
+  // 在失去焦点时,如果输入内容不包含逗号且不为空,将其格式化为逗号分隔形式
+  if (val && !val.includes(',') && val.trim() !== '') {
+    const items = val.split(/\s+/).filter(item => item.trim() !== '');
+    if (items.length > 1) {
+      setValue1(items.join(','));
+      return;
+    }
+  }
+  setValue1(val);
+}}
src/packages/searchbar/searchbar.taro.tsx (1)

142-143: ⚠️ Potential issue

清空回调参数不完整

清空输入时,仅向onChange传入空字符串,遗漏了事件对象参数。这与其他onChange调用不一致,可能导致使用者在处理事件时遇到问题。

- onChange && onChange('')
+ onChange?.('', event)
🧰 Tools
🪛 Biome (1.9.4)

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

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

131-139: ⚠️ Potential issue

清空回调参数不完整

清空输入时,仅向onChange传入空字符串,遗漏了事件对象参数。这与其他onChange调用不一致,可能导致使用者在处理事件时遇到问题。

- onChange && onChange('')
+ onChange?.('', event)
🧰 Tools
🪛 Biome (1.9.4)

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


279-280: 🛠️ Refactor suggestion

标签渲染和清除按钮的条件逻辑需统一

Web版本使用{innerTag ? renderValueByTags() : renderClear()}表示只会渲染标签或清除按钮中的一个,而Taro版本中这两个元素是分开渲染的,可能同时显示。这种不一致可能导致用户体验差异。

-{innerTag ? renderValueByTags() : renderClear()}
+{innerTag && renderValueByTags()}
+{!innerTag && renderClear()}
🧹 Nitpick comments (5)
src/packages/searchbar/demos/taro/demo10.tsx (1)

15-25: 优化标签点击处理逻辑

当前实现在删除标签时,如果只剩下一个标签,会将其显示为没有逗号的单一值。建议考虑保持一致的数据格式处理,即使只有一个项目也使用同样的格式。此外,应当考虑空数组情况的处理。

onItemClick={(val: string) => {
  console.log('click', val)
  const arr = value1.split(',')
  const newArr = arr.filter((item: string) => item !== val)
- const newVal = newArr.length > 1 ? newArr.join(',') : newArr.join('')
+ const newVal = newArr.join(',')
  setValue1(newVal)
}}
src/packages/searchbar/searchbar.taro.tsx (4)

96-97: 代码规范:使用可选链操作符

根据静态分析工具建议,应使用可选链操作符替代逻辑与操作符,以提高代码一致性和可读性。

- onChange && onChange(eventValue, event)
+ onChange?.(eventValue, event)
🧰 Tools
🪛 Biome (1.9.4)

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


105-106: 代码规范:使用可选链操作符

根据静态分析工具建议,应使用可选链操作符替代逻辑与操作符,以提高代码一致性和可读性。

- onFocus && onFocus(event.detail?.value, event)
+ onFocus?.(event.detail?.value, event)
🧰 Tools
🪛 Biome (1.9.4)

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


116-117: 代码规范:使用可选链操作符

根据静态分析工具建议,应使用可选链操作符替代逻辑与操作符,以提高代码一致性和可读性。

- onBlur && onBlur(event.detail?.value, event)
+ onBlur?.(event.detail?.value, event)
🧰 Tools
🪛 Biome (1.9.4)

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


217-241: renderValueByTags函数良好实现,考虑优化边缘情况

新增的标签渲染功能实现完善,但在value为空时使用setTimeout强制聚焦可能导致用户体验问题。当前实现在空值情况下立即执行forceFocus,可能会干扰用户的正常操作流程。

const renderValueByTags = useCallback(() => {
  if (!innerTag) return null
  if (!value) {
-   setTimeout(() => {
-     forceFocus()
-   }, 0)
+   // 只在组件挂载或value变为空时聚焦,避免不必要的频繁聚焦
+   useEffect(() => {
+     if (!value) {
+       forceFocus()
+     }
+   }, [value, forceFocus])
    return null
  }
  const list = value.split(',')
  if (!list) return null
  return (
    // 其余代码保持不变
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 1937622 and 5833294.

📒 Files selected for processing (4)
  • src/packages/searchbar/demos/taro/demo10.tsx (1 hunks)
  • src/packages/searchbar/searchbar.scss (2 hunks)
  • src/packages/searchbar/searchbar.taro.tsx (4 hunks)
  • src/packages/searchbar/searchbar.tsx (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/packages/searchbar/searchbar.scss
🧰 Additional context used
🧠 Learnings (1)
src/packages/searchbar/searchbar.taro.tsx (1)
Learnt from: irisSong
PR: jdf2e/nutui-react#3209
File: src/packages/searchbar/searchbar.taro.tsx:111-124
Timestamp: 2025-05-02T01:45:09.567Z
Learning: 在 React/Taro 组件中使用 setTimeout 或 setInterval 时,应当在组件卸载时通过 useEffect 的清理函数清除定时器,以防止内存泄漏。可以使用 useState 存储定时器 ID,并在 useEffect 的返回函数中清除。
🧬 Code Graph Analysis (1)
src/packages/searchbar/searchbar.tsx (2)
src/hooks/use-props-value.ts (1)
  • usePropsValue (11-35)
src/packages/calendarcard/icon.taro.tsx (1)
  • ArrowLeft (44-44)
🪛 Biome (1.9.4)
src/packages/searchbar/searchbar.taro.tsx

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 297-298: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

src/packages/searchbar/searchbar.tsx

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

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

111-128: 定时器处理优化已应用

很好!根据之前的学习反馈,您已正确实现了定时器的清理,通过useState存储定时器ID并在组件卸载时清除,防止内存泄漏。这是React组件中处理setTimeout的最佳实践。

🧰 Tools
🪛 Biome (1.9.4)

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

src/packages/searchbar/searchbar.tsx (1)

73-79: 使用usePropsValue进行状态管理的良好实践

使用usePropsValue来处理受控与非受控组件的状态管理是一个很好的改进。这样可以更好地支持默认值和控制值的切换,提高组件的灵活性。

Comment on lines +279 to +287
}, [right])

const renderClear = useCallback(() => {
return (
<View
className={`${classPrefix}-clear ${classPrefix}-icon`}
onClick={(e: any) => clearaVal(e)}
className={`${classPrefix}-clear ${classPrefix}-icon`}
style={{
visibility: `${!innerTag && value && clearable ? 'visible' : 'hidden'}`,
}}
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

考虑统一Web和Taro版本的渲染逻辑

Taro版本中renderValueByTagsrenderClear可以同时显示,而Web版本使用三元表达式(innerTag ? renderValueByTags() : renderClear())使它们互斥。这种不一致可能导致用户在不同平台上体验差异。建议统一两个版本的实现方式。


🏁 Script executed:

#!/bin/bash
# 查找Web版本中相关渲染逻辑
echo "Web版本的渲染逻辑:"
rg -n "renderValueByTags|renderClear" src/packages/searchbar/searchbar.tsx
echo "======================"
echo "Taro版本的渲染逻辑:"
rg -n "renderValueByTags|renderClear" src/packages/searchbar/searchbar.taro.tsx

Length of output: 754


统一 Web 与 Taro 版本的渲染逻辑

目前两端实现不一致,导致用户体验差异:

  • Web 版本(src/packages/searchbar/searchbar.tsx:279)使用
    {innerTag ? renderValueByTags() : renderClear()}
    ——互斥渲染,仅展示标签或清除按钮之一。
  • Taro 版本(src/packages/searchbar/searchbar.taro.tsx:310–311)使用
    {renderValueByTags()}
    {renderClear()}
    ——同时渲染,两个组件都会存在但通过样式控制可见性。

建议统一为同一种模式:

  • 若意图互斥渲染:Taro 端改为 {innerTag ? renderValueByTags() : renderClear()}
  • 若意图同时渲染仅调整可见性:Web 端改为同时调用并通过 visibility/display 控制。

请根据产品设计调整并同步更新两端实现。

Comment on lines +142 to +153
const onKeydown = useCallback(
(e: React.KeyboardEvent) => {
if (e.key === 'Enter') {
const event = e.nativeEvent
if (typeof event.cancelable !== 'boolean' || event.cancelable) {
event.preventDefault()
}
onSearch && onSearch(value as string)
}
},
[onSearch, value]
)
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

键盘事件处理逻辑缺少测试覆盖

新增的键盘事件处理逻辑看起来实现良好,但静态分析工具报告该代码段未被测试覆盖。应当添加针对Enter键触发搜索功能的单元测试,确保其按预期工作。


🏁 Script executed:

#!/bin/bash
# 检查是否有对应的键盘事件测试
echo "搜索在测试文件中是否有键盘事件相关测试:"
grep -r "onKeyDown\|press.*Enter\|key.*event" src/packages/searchbar/__tests__

Length of output: 352


🏁 Script executed:

#!/bin/bash
# 在所有测试文件中搜索 Enter 关键字
echo "搜索 Enter 关键字:"
rg "Enter" -n -g "*.test.tsx" -g "*.test.ts" -g "*.spec.tsx" -g "*.spec.ts"
# 在所有测试文件中搜索 onKeydown 调用
echo "搜索 onKeydown:"
rg "onKeydown" -n -g "*.test.tsx" -g "*.test.ts" -g "*.spec.tsx" -g "*.spec.ts"

Length of output: 229


添加 Enter 键触发搜索的单元测试

当前位于 src/packages/searchbar/searchbar.tsxonKeydown 回调在现有测试中未被覆盖,需要补充针对 Enter 键触发搜索的测试:

  • 测试文件:在 src/packages/searchbar/__tests__/searchbar.test.tsx(或同级测试目录)中新增
  • 场景一:当输入框有值时,模拟用户按下 Enter,断言 onSearch 被调用且参数等于输入值
  • 场景二:当输入框为空时,模拟按下 Enter,断言 onSearch 不被调用
  • 建议使用 React Testing Library 的 fireEvent.keyDownuserEvent.keyboard('{Enter}')

请补充以上测试以确保键盘事件逻辑得到充分验证。

🧰 Tools
🪛 Biome (1.9.4)

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

Comment on lines +194 to +216
if (!value) {
setTimeout(() => {
forceFocus()
}, 0)
return null
}
const list = value.split(',')
if (!list) return null
return (
<div className="nut-searchbar-values">
{list.map((item, index) => (
<div
key={`def-${index}`}
className="nut-searchbar-value"
onClick={(e) => onItemClick?.(item, e)}
>
{item}
<Close />
</div>
))}
</div>
)
}, [value, onItemClick])
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

renderValueByTags中setTimeout使用可能导致内存泄漏

renderValueByTags函数中使用了setTimeout但未在组件卸载时清除,这可能导致内存泄漏。应该和blur timer一样使用state存储timer ID并在组件卸载时清除。

+const [focusTimer, setFocusTimer] = useState<NodeJS.Timeout | null>(null)

const renderValueByTags = useCallback(() => {
  if (!value) {
-   setTimeout(() => {
+   const timer = setTimeout(() => {
      forceFocus()
    }, 0)
+   setFocusTimer(timer)
    return null
  }
  // 其余代码不变
}, [value, onItemClick])

useEffect(() => {
  return () => {
    if (blurTimer) clearTimeout(blurTimer)
+   if (focusTimer) clearTimeout(focusTimer)
  }
-}, [blurTimer])
+}, [blurTimer, focusTimer])

@xiaoyatong xiaoyatong requested a review from Miles-hxy May 5, 2025 01:57
@xiaoyatong
Copy link
Collaborator Author

image 点击popover没有展示 页面有遮罩卡住了

在popover 中修改。

style={{
visibility: `${!innerTag && value && clearable ? 'visible' : 'hidden'}`,
}}
onClick={clearaVal}
Copy link
Collaborator

@oasis-cloud oasis-cloud May 8, 2025

Choose a reason for hiding this comment

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

onTouchStart 和 onMousedown 早于 onBlur 事件,可以阻止默认行为防止失去焦点。实际体验下效果和定时器的差不多。
建议考虑去掉失去焦点保持键盘的逻辑。

@oasis-cloud oasis-cloud merged commit 9b99c2c into jdf2e:feat_v3.x May 15, 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/XXL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants