Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: picker #2990

Merged
merged 56 commits into from
Feb 27, 2025
Merged

refactor: picker #2990

merged 56 commits into from
Feb 27, 2025

Conversation

irisSong
Copy link
Collaborator

@irisSong irisSong commented Feb 14, 2025

🤔 这个变动的性质是?

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

🔗 相关 Issue

💡 需求背景和解决方案

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

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

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

Summary by CodeRabbit

  • 新功能
    • 新增 PickerView 组件,为用户提供全新的选择视图体验。
  • 重构
    • 优化了数据录入、日期选择器和选择器组件的交互逻辑,统一了显示属性,增强了稳定性。
    • 移除了 PickerOption 接口,采用新的 PickerOptions 和 PickerValue 类型,提升了类型安全性。
    • 更新了多个组件的参数类型,确保一致性和类型安全。
    • 更新了 Picker 组件的内部状态管理,简化了选项处理逻辑,提升了可读性和维护性。
  • 样式
    • 精简并优化了选择器组件的样式,实现了界面更现代、简洁的视觉效果。

Copy link
Collaborator

@xiaoyatong xiaoyatong left a comment

Choose a reason for hiding this comment

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

1、弹出时,没有动效了
2、建议默认有值被选中,参考线上
image
3、datepicker 平闰年处理:慢慢往上拖年份的时候会出现。
image

const columns = container.querySelectorAll('.nut-picker-list')[0]
const lists = columns.querySelectorAll('.nut-picker-roller-item-title')
const years = ['2020', '2021', '2022']
const columns = container.querySelectorAll('.nut-pickerview-list')[0]
Copy link
Collaborator

Choose a reason for hiding this comment

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

参考 ai 反馈

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

参考 ai 反馈

已修改

import { useConfig } from '@/packages/configprovider/index.taro'
import { usePropsValue } from '@/hooks/use-props-value'
import { BasicComponent, ComponentDefaults } from '@/utils/typings'
import { isDate } from '@/utils/is-date'
import { padZero } from '@/utils/pad-zero'
import { PickerOptionItem, PickerValue } from '@/packages/pickerview/index.taro'
Copy link
Collaborator

@xiaoyatong xiaoyatong Feb 25, 2025

Choose a reason for hiding this comment

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

这里是否可以直接引用 types.ts

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

这里是否可以直接引用 types.ts

已修改

@@ -38,17 +39,17 @@ export interface DatePickerProps extends BasicComponent {
| 'onChange'
>
>
formatter: (type: string, option: PickerOption) => PickerOption
filter: (type: string, option: PickerOption[]) => PickerOption[]
formatter: (type: string, option: PickerOptionItem) => PickerOptionItem
Copy link
Collaborator

Choose a reason for hiding this comment

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

我个人理解这里不需要突出 item,PickerOption 和 PickerOptions 可以标明他们的单复数~

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

我个人理解这里不需要突出 item,PickerOption 和 PickerOptions 可以标明他们的单复数~

已修改

onClose: () => void
onCancel: () => void
onConfirm: (
selectedOptions: PickerOption[],
selectedValue: (string | number)[]
selectedOptions: PickerOptionItem[],
Copy link
Collaborator

Choose a reason for hiding this comment

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

这里 可以直接使用 PickerOptions 了,types 有定义。

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

这里 可以直接使用 PickerOptions 了,types 有定义。

已修改

SafeArea,
Popup,
PopupProps,
} from '@nutui/nutui-react'
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.

引相对路径就可以。
已修改

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 (2)
src/packages/picker/demos/h5/demo7.tsx (1)

54-87: 🛠️ Refactor suggestion

优化异步数据更新逻辑

当前代码存在以下需要优化的地方:

  1. 直接修改状态数组可能导致意外的副作用
  2. 使用 setTimeout(fn, 0) 是一种反模式

建议使用不可变的方式更新状态:

-      asyncData[0][1].children = [
-        // ... data
-      ]
-      setAsyncData([...[...asyncData]])
+      setAsyncData((prevData) => {
+        const newData = JSON.parse(JSON.stringify(prevData))
+        newData[0][1].children = [
+          // ... data
+        ]
+        return newData
+      })

对于异步数据加载,建议:

  1. 使用 Promise 或 async/await
  2. 添加加载状态指示
  3. 实现错误处理机制
src/packages/picker/demos/taro/demo7.tsx (1)

54-87: 🛠️ Refactor suggestion

优化异步数据更新逻辑

当前代码存在以下需要优化的地方:

  1. 直接修改状态数组可能导致意外的副作用
  2. 使用 setTimeout(fn, 0) 是一种反模式

建议使用不可变的方式更新状态:

-      asyncData[0][1].children = [
-        // ... data
-      ]
-      setAsyncData([...[...asyncData]])
+      setAsyncData((prevData) => {
+        const newData = JSON.parse(JSON.stringify(prevData))
+        newData[0][1].children = [
+          // ... data
+        ]
+        return newData
+      })

对于异步数据加载,建议:

  1. 使用 Promise 或 async/await
  2. 添加加载状态指示
  3. 实现错误处理机制
🧹 Nitpick comments (4)
src/packages/pickerview/__test__/pickerview.spec.tsx (1)

161-166: 考虑使用 act 和 waitFor 优化测试

建议重构测试逻辑,使用 actwaitFor 而不是依赖 setTimeout,这样可以确保测试的稳定性。

-  const { container } = render(<PenderContent />)
-
-  await waitFor(() => {
-    expect(container).toMatchSnapshot()
-  })
+  const { container } = render(<PenderContent />)
+
+  await act(async () => {
+    await waitFor(() => {
+      expect(container).toMatchSnapshot()
+    })
+  })
src/packages/datepicker/demos/h5/demo2.tsx (1)

16-18: 参数类型和实现更新

函数参数类型从 (values: (string | number)[], options: PickerOption[]) 更改为 (values: PickerValue[], options: PickerOptions),并且在映射函数中使用 option.label 替代了 option.text

控制台日志输出可帮助调试,但在生产环境中可能需要移除。

考虑在生产环境中移除控制台日志输出:

-  const confirm = (values: PickerValue[], options: PickerOptions) => {
-    console.log('values', values, options)
-    setDesc(options.map((option) => option.label).join('-'))
+  const confirm = (values: PickerValue[], options: PickerOptions) => {
+    setDesc(options.map((option) => option.label).join('-'))
src/packages/datepicker/datepicker.tsx (1)

414-420: 使用可选链优化代码

根据静态分析工具的建议,这段代码可以使用可选链操作符来优化:

-          onConfirm={(
-            selectedOptions: PickerOptions,
-            selectedValue: PickerValue[]
-          ) => onConfirm && onConfirm(selectedOptions, selectedValue)}
+          onConfirm={(
+            selectedOptions: PickerOptions,
+            selectedValue: PickerValue[]
+          ) => onConfirm?.(selectedOptions, selectedValue)}

使用可选链可以简化代码并保持同样的功能。

🧰 Tools
🪛 Biome (1.9.4)

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

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

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

在调用 onConfirm 函数时可以使用可选链操作符,以简化代码并提高可读性。

-onConfirm={(selectedOptions: PickerOptions, selectedValue: PickerValue[]) => onConfirm && onConfirm(selectedOptions, selectedValue)}
+onConfirm={(selectedOptions: PickerOptions, selectedValue: PickerValue[]) => onConfirm?.(selectedOptions, selectedValue)}
🧰 Tools
🪛 Biome (1.9.4)

[error] 423-423: 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 f6edf91 and 9688104.

📒 Files selected for processing (41)
  • src/packages/datepicker/__test__/datepicker.spec.tsx (6 hunks)
  • src/packages/datepicker/datepicker.taro.tsx (8 hunks)
  • src/packages/datepicker/datepicker.tsx (8 hunks)
  • src/packages/datepicker/demos/h5/demo1.tsx (3 hunks)
  • src/packages/datepicker/demos/h5/demo2.tsx (2 hunks)
  • src/packages/datepicker/demos/h5/demo3.tsx (2 hunks)
  • src/packages/datepicker/demos/h5/demo4.tsx (2 hunks)
  • src/packages/datepicker/demos/h5/demo5.tsx (2 hunks)
  • src/packages/datepicker/demos/h5/demo6.tsx (2 hunks)
  • src/packages/datepicker/demos/h5/demo7.tsx (2 hunks)
  • src/packages/datepicker/demos/h5/demo8.tsx (3 hunks)
  • src/packages/datepicker/demos/taro/demo1.tsx (2 hunks)
  • src/packages/datepicker/demos/taro/demo2.tsx (1 hunks)
  • src/packages/datepicker/demos/taro/demo3.tsx (2 hunks)
  • src/packages/datepicker/demos/taro/demo4.tsx (2 hunks)
  • src/packages/datepicker/demos/taro/demo5.tsx (2 hunks)
  • src/packages/datepicker/demos/taro/demo6.tsx (2 hunks)
  • src/packages/datepicker/demos/taro/demo7.tsx (2 hunks)
  • src/packages/datepicker/demos/taro/demo8.tsx (3 hunks)
  • src/packages/picker/demos/h5/demo1.tsx (2 hunks)
  • src/packages/picker/demos/h5/demo6.tsx (1 hunks)
  • src/packages/picker/demos/h5/demo7.tsx (2 hunks)
  • src/packages/picker/demos/h5/demo8.tsx (2 hunks)
  • src/packages/picker/demos/taro/demo1.tsx (2 hunks)
  • src/packages/picker/demos/taro/demo6.tsx (1 hunks)
  • src/packages/picker/demos/taro/demo7.tsx (2 hunks)
  • src/packages/picker/demos/taro/demo8.tsx (2 hunks)
  • src/packages/picker/picker.taro.tsx (6 hunks)
  • src/packages/picker/picker.tsx (6 hunks)
  • src/packages/pickerview/__test__/pickerview.spec.tsx (1 hunks)
  • src/packages/pickerview/doc.en-US.md (1 hunks)
  • src/packages/pickerview/doc.md (1 hunks)
  • src/packages/pickerview/doc.taro.md (1 hunks)
  • src/packages/pickerview/doc.zh-TW.md (1 hunks)
  • src/packages/pickerview/index.taro.ts (1 hunks)
  • src/packages/pickerview/index.ts (1 hunks)
  • src/packages/pickerview/pickerroller.taro.tsx (5 hunks)
  • src/packages/pickerview/pickerroller.tsx (5 hunks)
  • src/packages/pickerview/pickerview.taro.tsx (7 hunks)
  • src/packages/pickerview/pickerview.tsx (7 hunks)
  • src/packages/pickerview/types.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (16)
  • src/packages/datepicker/demos/h5/demo4.tsx
  • src/packages/datepicker/test/datepicker.spec.tsx
  • src/packages/datepicker/demos/h5/demo3.tsx
  • src/packages/datepicker/demos/taro/demo3.tsx
  • src/packages/datepicker/demos/taro/demo7.tsx
  • src/packages/datepicker/demos/h5/demo7.tsx
  • src/packages/datepicker/demos/taro/demo2.tsx
  • src/packages/datepicker/demos/taro/demo6.tsx
  • src/packages/datepicker/demos/h5/demo5.tsx
  • src/packages/datepicker/demos/taro/demo8.tsx
  • src/packages/picker/demos/h5/demo1.tsx
  • src/packages/picker/demos/h5/demo8.tsx
  • src/packages/datepicker/demos/taro/demo1.tsx
  • src/packages/datepicker/demos/taro/demo4.tsx
  • src/packages/datepicker/demos/h5/demo6.tsx
  • src/packages/datepicker/demos/h5/demo1.tsx
🧰 Additional context used
🧠 Learnings (1)
src/packages/pickerview/__test__/pickerview.spec.tsx (1)
Learnt from: xiaoyatong
PR: jdf2e/nutui-react#2990
File: src/packages/pickerview/__test__/pickerview.spec.tsx:0-0
Timestamp: 2025-02-25T02:21:32.906Z
Learning: In React component tests, avoid using setTimeout with fixed delays. Instead, use act() to wrap async state updates and waitFor() for assertions, which makes tests more stable and reliable.
🪛 GitHub Check: codecov/patch
src/packages/picker/picker.tsx

[warning] 223-225: src/packages/picker/picker.tsx#L223-L225
Added lines #L223 - L225 were not covered by tests


[warning] 230-230: src/packages/picker/picker.tsx#L230
Added line #L230 was not covered by tests

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

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

src/packages/datepicker/datepicker.taro.tsx

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🔇 Additional comments (100)
src/packages/pickerview/index.ts (1)

5-5: 类型导出命名调整为更一致的形式

PickerOptionItem 重命名为 PickerOption 使类型命名更加简洁和一致,这有助于简化代码库中的类型引用。

src/packages/pickerview/__test__/pickerview.spec.tsx (2)

136-136: 增强类型安全,明确状态变量类型

value 状态变量添加显式类型注解 [] as number[] 提高了类型安全性,明确了数组元素只能是数字类型。


139-146: 🛠️ Refactor suggestion

异步更新测试需要优化

当前的异步测试使用了固定的延时时间(1000ms),这可能导致测试不稳定。建议使用 act 包装异步操作,并考虑使用更可靠的等待机制。

-    useEffect(() => {
-      const timer = setTimeout(() => {
-        setInnerOptions(listData)
-        setValue([1])
-      }, 1000)
-
-      return () => clearTimeout(timer) // 清理定时器
-    }, [])
+    useEffect(() => {
+      setInnerOptions(listData)
+      setValue([1])
+    }, [])
src/packages/pickerview/index.taro.ts (1)

5-5: 统一类型命名约定

PickerOptionItem 更新为 PickerOption,与非 Taro 版本保持一致,确保代码库中的类型命名统一。

src/packages/pickerview/pickerroller.taro.tsx (5)

11-11: 更新导入的类型名称

将导入类型 PickerOptionItem 更新为 PickerOption,保持整个代码库中类型命名的一致性。


26-26: 更新函数参数类型

renderLabel 函数参数 item 的类型从 PickerOptionItem 更新为 PickerOption,确保类型一致性。


135-137: 增加明确的类型注解

findIndex 方法中为 item 参数添加了明确的 PickerOption 类型注解,提高了代码的类型安全性。


228-228: 为映射函数参数添加类型注解

options.map 回调函数的参数添加了明确的类型注解,提高了代码的类型安全性和可读性。


241-241: 为非 3D 视图映射函数参数添加类型注解

同样在非 3D 视图的 options.map 回调函数中添加了明确的类型注解,保持了代码风格一致性。

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

74-74: 类型命名更新

这里将标题从 PickerOptionItem 更改为 PickerOption,与代码库中的类型重命名保持一致。这种更新有助于维护文档与代码之间的一致性。


80-80: 类型定义更新

children 属性的类型从 PickerOptionItem[] 更改为 PickerOptions,与代码库中的类型重构保持一致。这样的改动有助于提高类型安全性和代码可读性。

src/packages/datepicker/demos/taro/demo5.tsx (2)

2-7: 导入类型更新

@nutui/nutui-react-taro 导入 PickerValuePickerOptions 类型,替换了之前使用的 PickerOption 类型,与整体重构方向一致。


18-19: 函数参数类型和属性访问方式更新

  1. confirm 函数的参数类型从 PickerOption[](string | number)[] 更新为 PickerOptionsPickerValue[]
  2. 将属性访问从 option.text 更改为 option.label

这些变更与整个代码库中的类型重构和属性命名规范更新保持一致。

src/packages/pickerview/pickerview.tsx (8)

15-15: 导入类型重命名

将导入的类型从 PickerOptionItem 更改为 PickerOption,保持与整个代码库的类型重命名一致。


26-26: 函数参数类型更新

renderLabel 函数的参数类型从 PickerOptionItem 更新为 PickerOption,确保与重命名的类型定义保持一致。


79-79: 变量类型声明更新

columnOptions 变量的类型从 PickerOptionItem 更新为 PickerOption,与类型重命名保持一致。


97-97: 回调函数参数类型更新

findIndex 回调函数中参数的类型注解从 PickerOptionItem 更新为 PickerOption,确保类型一致性。


133-133: 事件处理函数参数类型更新

handleSelect 函数的参数类型从 PickerOptionItem 更新为 PickerOption,保持类型定义的一致性。


161-161: 类型断言更新

optionFirst 的类型断言从 PickerOptionItem[] 更新为 PickerOptions,保持与新的类型命名约定一致。


179-179: 回调函数参数类型更新

find 回调函数中参数的类型注解从 PickerOptionItem 更新为 PickerOption,确保类型一致性。


184-184: 返回值类型断言更新

将过滤后数组的类型断言从 PickerOptionItem[] 更新为 PickerOptions,与整体类型重构保持一致。

src/packages/pickerview/doc.md (2)

74-74: 类型命名更新

这里将标题从 PickerOptionItem 更改为 PickerOption,与代码库中的类型重命名保持一致。这种更新有助于维护文档与代码之间的一致性。


80-80: 类型定义更新

children 属性的类型从 PickerOptionItem[] 更改为 PickerOptions,与代码库中的类型重构保持一致。这样的改动有助于提高类型安全性和代码可读性。

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

74-74: 类型重命名更新

类型名称从 PickerOptionItem 更改为 PickerOption,保持了命名上的一致性,符合组件库的整体重构方向。


80-80: 级联选项类型更新

children 属性的类型从 PickerOptionItem[] 更改为 PickerOptions,类型定义更加统一,有利于提高代码的一致性和可维护性。

src/packages/datepicker/demos/h5/demo2.tsx (1)

2-7: 类型导入更新

从组件库中导入了 PickerOptionsPickerValue 类型来替代之前的 PickerOption,符合类型系统的重构方向。

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

16-17: 导入类型更新

更新导入的类型名称,从 PickerOptionItem 更改为 PickerOption,保持类型系统的一致性。


27-28: 渲染函数参数类型更新

renderLabel 函数的参数类型从 PickerOptionItem 更新为 PickerOption,与新的类型定义保持一致。


80-84: 变量类型定义更新

columnOptions 变量的类型从 PickerOptionItem 更新为 PickerOption,属性名称保持一致且符合类型系统的变更。


98-99: 回调函数参数类型更新

findIndex 方法的回调函数参数类型从 PickerOptionItem 更新为 PickerOption,保持类型系统一致性。


134-135: 函数参数类型更新

handleSelect 函数的参数类型从 PickerOptionItem 更新为 PickerOption,与整体类型系统变更保持一致。


162-163: 类型转换更新

optionFirst 变量的类型转换从 PickerOptionItem[] 更新为 PickerOptions,确保类型一致性。


180-181: 回调函数参数类型更新

find 方法的回调函数参数类型从 PickerOptionItem 更新为 PickerOption,保持类型系统的一致性。


185-186: 返回类型更新

filter 方法的返回类型从 PickerOptionItem[] 更新为 PickerOptions,确保类型转换的正确性和一致性。

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

74-74: 类型名称更新

英文文档中将类型名称从 PickerOptionItem 更改为 PickerOption,与中文文档保持一致,确保文档的统一性。


80-80: 级联选项类型更新

英文文档中将 children 属性的类型从 PickerOptionItem[] 更改为 PickerOptions,与中文文档保持一致,确保类型系统的统一性。

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

2-9: 导入类型定义更新

引入了新的类型定义 PickerOptionsPickerValue,更好地规范了组件的类型约束。这与整体重构中对 Picker 相关类型的统一调整保持一致。


28-36: 参数类型和属性访问更新

函数参数类型从 PickerOption[] 更新为更明确的 PickerOptions 类型,同时将属性访问从 option.text 更改为 option.label。这样的变更保持了与其他 Picker 组件的一致性。


55-61: 组件样式属性和事件处理更新

样式属性和事件处理函数签名已更新,使用了新的类型定义。这些变更使组件接口更加一致和类型安全。

src/packages/pickerview/pickerroller.tsx (4)

10-10: 类型导入更新

PickerOptionItem 更新为 PickerOption,保持与整个库中类型定义的一致性。


24-24: 渲染标签函数参数类型更新

renderLabel 函数的参数类型从 PickerOptionItem 更新为 PickerOption,确保类型一致性。


133-135: 查找索引回调函数类型更新

findIndex 方法中明确指定了回调函数参数的类型为 PickerOption,提高了代码的类型安全性。


215-215: 映射函数参数类型更新

options.map 函数调用中显式指定了 item 参数的类型为 PickerOption,增强了代码的类型安全性和可读性。

Also applies to: 228-228

src/packages/picker/demos/taro/demo6.tsx (5)

2-8: 导入类型定义更新

引入了新的类型定义 PickerOptionsPickerValue,更好地规范了组件的类型约束。这与整体重构中对 Picker 相关类型的统一调整保持一致。


12-13: 状态管理优化

添加了新的 value 状态变量并初始化为特定值,同时为 cityCustom 提供了默认值。这样可以确保组件初始化时有合理的默认值,提高用户体验。


14-73: 建议提取共享的数据和工具函数

h5 和 taro 版本的 demo 中存在大量重复的数据结构和逻辑。建议将这些共同部分提取到共享文件中。

建议创建一个共享的数据文件:

// shared/cityData.ts
export const customCityData = [
  [
    {
      value: 1,
      label: '北京',
      children: [
        // ... existing data
      ],
    },
    // ... remaining data
  ],
]

然后在两个 demo 文件中导入:

-const customCityData = [ ... ]
+import { customCityData } from '../shared/cityData'

75-85: 回调函数参数类型和属性访问更新

setChooseValueCustom 函数的参数类型更新为 PickerOptionsPickerValue[],同时属性访问从 item.text 更改为 item.label。这样的变更与整体重构中的类型调整保持一致,提高了代码的类型安全性。


98-103: 事件处理函数更新

更新了 value 属性和事件处理函数,使用了新的类型定义。onChange 函数参数使用解构赋值,代码更加简洁。

src/packages/datepicker/demos/h5/demo8.tsx (4)

2-8: 导入类型定义更新

引入了新的类型定义 PickerOptionsPickerValue,更好地规范了组件的类型约束。这与整体重构中对 DatePicker 相关类型的统一调整保持一致。


20-22: 确认函数参数类型更新

confirm 函数的参数类型从 (values: (string | number)[], options: PickerOption[]) 更新为 (values: PickerValue[], options: PickerOptions),同时属性访问使用新的 label 属性。这些变更与统一的类型定义保持一致。


23-28: 过滤函数参数类型更新

filter 函数的参数类型从 options: PickerOption[] 更新为 options: PickerOptions,使类型定义更加统一。


29-47: 格式化函数属性访问更新

formatter1 函数中,将对选项的属性访问从 option.text 更改为 option.label。这样的变更保持了与其他 Picker 组件的一致性,提高了代码的可维护性。

src/packages/picker/demos/taro/demo1.tsx (5)

2-9: 导入更新适应类型更改

导入了新的类型定义,这对重构后的 Picker 组件是必要的。引入 PickerOptionsPickerValuePickerOnChangeCallbackParameter 类型有助于提高类型安全性。


14-26: 属性名称从 text 更改为 label

将数组名从 listData1 更改为更具描述性的 options,并且将对象属性从 text 更改为 label,符合组件重构的一致性要求。


27-33: 回调函数签名优化

从使用多个独立参数改为使用单个结构化参数,提高了函数接口的清晰度和可维护性。


34-44: 确认函数参数类型更新

确认函数参数类型已更新为新的 PickerOptionsPickerValue[] 类型,并相应地更新了函数内部逻辑,使用 option.label 替代原来的 option.text


55-59: Picker 组件属性更新

Picker 组件的属性已更新以适应新的类型和命名约定,传递 options 数组和回调函数。

src/packages/picker/demos/h5/demo7.tsx (5)

2-9: 导入更新适应类型更改

导入了新的类型定义,这对重构后的 Picker 组件是必要的。引入 PickerOptionsPickerValuePickerOnChangeCallbackParameter 类型有助于提高类型安全性。


13-14: 状态初始化使用新的类型

使用 TypeScript 泛型 PickerValue[] 初始化 value 状态,并为 asyncDesc 提供默认值,增强了类型安全性和代码可读性。


15-53: 数据结构更新使用 label 替代 text

数据结构已更新为使用 label 代替 text,保持了与重构的一致性。


88-98: 确认函数参数类型更新

确认函数参数类型已更新为新的 PickerOptionsPickerValue[] 类型,并相应地更新了函数内部逻辑,使用 option.label 替代原来的 option.text。同时添加了 setValue 调用来更新状态。


107-115: Picker 组件属性更新

Picker 组件的属性已更新以适应新的类型和命名约定,传递 value 状态和更新的回调函数。

src/packages/picker/demos/taro/demo7.tsx (5)

2-9: 导入更新适应类型更改

导入了新的类型定义,这对重构后的 Picker 组件是必要的。引入 PickerOptionsPickerValuePickerOnChangeCallbackParameter 类型有助于提高类型安全性。


13-14: 状态初始化使用新的类型

使用 TypeScript 泛型 PickerValue[] 初始化 value 状态,并为 asyncDesc 提供默认值,增强了类型安全性和代码可读性。


15-53: 数据结构更新使用 label 替代 text

数据结构已更新为使用 label 代替 text,保持了与重构的一致性。


88-98: 确认函数参数类型更新

确认函数参数类型已更新为新的 PickerOptionsPickerValue[] 类型,并相应地更新了函数内部逻辑,使用 option.label 替代原来的 option.text。同时添加了 setValue 调用来更新状态。


107-115: Picker 组件属性更新

Picker 组件的属性已更新以适应新的类型和命名约定,传递 value 状态和更新的回调函数。

src/packages/picker/demos/h5/demo6.tsx (6)

2-8: 导入更新适应类型更改

导入了新的类型定义,这对重构后的 Picker 组件是必要的。引入 PickerOptionsPickerValue 类型有助于提高类型安全性。


12-13: 状态初始化使用新的类型

使用 TypeScript 泛型 PickerValue[] 初始化 value 状态,并为 cityCustom 提供默认值 '上海',增强了类型安全性和用户体验。


14-73: 数据结构更新使用 label 替代 text

数据结构已更新为使用 label 代替 text,保持了与重构的一致性。嵌套的子选项也进行了相应更新。


75-85: 选择值函数参数类型更新

选择值函数参数类型已更新为新的 PickerOptionsPickerValue[] 类型,并相应地更新了函数内部逻辑,使用 item.label 替代原来的 item.text。同时添加了 setValue 调用来更新状态。


89-93: Cell 组件标题更新

Cell 组件的标题从"多级联动"更改为"请选择城市",使界面文本更加明确和一致。


98-104: Picker 组件属性和回调更新

Picker 组件添加了 value 属性并更新了 onChange 回调的实现,使用了解构赋值来获取参数,提高了代码的可读性。回调函数中的控制台输出也更新为使用新的参数名称。

src/packages/picker/picker.taro.tsx (7)

8-24: 优化了导入和类型定义

代码重构后,使用了更清晰的类型结构,从 pickerview 模块导入了更通用的类型定义。同时添加了必要的组件导入,如 PickerView 和 SafeArea,使得代码结构更加模块化。


29-49: 类型定义更加明确和统一

接口 PickerProps 的类型定义得到优化:

  • options 从 (PickerOption | PickerOption[])[] 变为更简洁的 PickerOptions[]
  • value 和 defaultValue 更新为 PickerValue[]
  • 回调函数签名更新,使用了更明确的类型

这些变更使得类型系统更加一致,提高了代码的可维护性。


115-119: 状态管理逻辑优化

重构后的状态管理更加清晰:

  • 使用了更明确的状态变量命名
  • 添加了引用类型的状态管理
  • 使用 useState 和 useRef 结合管理复杂状态

这种方式既保证了状态更新的性能,又提高了代码的可读性。


128-145: 回调处理逻辑优化

onChangeItem 函数重构得很好:

  • 使用解构赋值简化参数处理
  • 通过 isEqual 避免不必要的状态更新
  • 通过引用更新 selectedOptionsRef 确保数据一致性

这种方式可以减少不必要的渲染并提高组件性能。


191-213: UI 渲染逻辑更加模块化

使用 renderPickerElement 函数封装渲染逻辑,这是一个很好的重构:

  • 将复杂的渲染逻辑封装到单独的函数中
  • 使用新的 PickerView 组件替代旧的实现
  • 清晰地传递所需的属性和回调

这使得代码更加可读,也便于维护。


219-232: Popup 组件使用优化

Popup 组件的使用变得更加简洁和条件化:

  • 使用条件渲染避免不必要的组件实例化
  • 添加了 SafeArea 组件提高在不同设备上的显示效果
  • 简化了 onOverlayClick 处理逻辑

这些变更提高了组件的性能和用户体验。


237-237: 类型导出更加准确

forwardRef 的类型从 unknown 更新为具体的 PickerRef,这可以提供更好的类型安全性和自动补全支持。

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

9-23: 优化了导入和类型定义

类似于 Taro 版本,Web 版本也更新了导入和类型定义,保持了两个平台的一致性。使用了 pickerview 模块中的类型,简化了类型结构。


28-48: 统一的接口定义

PickerProps 接口的更新与 Taro 版本保持一致,确保了跨平台的类型一致性。这种统一的类型定义有助于减少平台特定的代码差异。


114-118: 状态管理优化

同样优化了状态管理,使用相同的模式管理状态。这种一致性有助于跨平台代码的维护和理解。


190-213: UI 渲染模块化

使用 renderPickerElement 函数封装渲染逻辑,提高代码的可读性和可维护性。Web 版本使用 div 和 span 元素而不是 View 组件,符合 Web 平台的特性。

src/packages/pickerview/types.ts (4)

5-11: 类型结构优化

重构后的类型定义更加清晰:

  • PickerOption 作为基本类型单元
  • 定义 PickerOptions 作为 PickerOption 的数组类型
  • 明确了属性名称,使用 label 替代之前的 text

这种类型结构使得代码更加自解释,同时保持了类型的一致性。


13-21: 接口更新与类型一致

PickerRollerProps 接口的更新与新的类型定义保持一致:

  • options 类型更新为 PickerOptions
  • onSelect 和 renderLabel 函数签名更新为使用 PickerOption

这确保了类型系统的一致性,减少了潜在的类型错误。


23-27: 回调参数类型更新

PickerOnChangeCallbackParameter 接口的 selectedOptions 属性类型从数组更新为 PickerOptions,与整体类型系统保持一致。这种一致性使得类型检查更加可靠。


29-38: PickerViewProps 接口更新

PickerViewProps 接口也进行了相应更新,保持与其他接口的一致性。整个类型系统的一致性是这次重构的一个重要方面,有助于提高代码质量。

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

8-12: 导入更新与类型系统一致

从 pickerview 模块导入了新的类型定义,保持与整体类型系统的一致性。这种变更确保了 DatePicker 组件可以无缝使用 Picker 组件的更新。


46-57: 接口更新符合新的类型系统

DatePickerProps 接口的更新与 Picker 组件的类型变更保持一致:

  • filter 方法参数更新为 PickerOptions
  • onConfirm 和 onChange 方法使用新的类型定义

这种一致性确保了组件间的兼容性和类型安全。


111-112: 状态变量类型更新

状态变量 pickerValue 和 pickerOptions 的类型更新为新的类型定义,保持与其他更改的一致性。这是重构的重要部分,确保类型系统的完整性。


320-326: 属性名从 text 改为 label

formatOption 函数返回的对象属性从 text 改为 label,符合新的类型定义。这是一个重要的变更,确保了与新类型系统的兼容性。

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

9-13: 导入从单一文件获取类型定义,提高了代码组织性

导入使用了新的类型定义 PickerOptionPickerOptionsPickerValue,这符合类型系统的规范化。


47-47: 参数类型更新为 PickerOptions

filter 函数的参数类型从 PickerOption[] 更新为 PickerOptions,确保了类型一致性。


51-53: 回调函数参数类型更新

onConfirm 回调函数的参数类型从旧的类型更新为 PickerOptionsPickerValue[],与新的类型系统保持一致。


55-58: onChange 回调函数参数类型更新

onChange 回调函数的参数类型也更新为 PickerOptionsPickerValue[],保持了类型系统的一致性。


112-113: 状态类型更新

将状态变量 pickerValuepickerOptions 的类型分别更新为 PickerValue[]PickerOptions[],与新的类型定义保持一致。


321-323: 属性名从 text 更改为 label

将选项的属性名从 text 更改为 label,这是此次重构的核心变更之一,使命名更加直观和统一。


327-327: 返回对象属性名更新

返回对象的属性名从 text 更改为 label,与整体重构保持一致。


424-426: handlePickerChange 调用参数更新

更新了 onChange 回调中 handlePickerChange 的调用,以适应新的参数类型和结构。

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (3)
src/packages/picker/picker.taro.tsx (2)

145-145: 移除调试代码

这里有一个调试用的 console.log 语句,应该在提交前删除。

-    console.log('sss')

120-126: 优化 useEffect 依赖项

当前的依赖项数组包含 innerOptions,但是这个状态也在 effect 内部被更新,这可能会导致不必要的重新渲染。

  useEffect(() => {
    if (innerVisible) {
      setInnerValue(selectedValue)
      setInnerOptions(options as PickerOptions[])
    }
-  }, [selectedValue, innerOptions, innerVisible])
+  }, [selectedValue, options, innerVisible])
src/packages/picker/picker.tsx (1)

120-126: 优化 useEffect 依赖项

当前的依赖项数组包含 innerOptions,但是这个状态也在 effect 内部被更新,这可能会导致不必要的重新渲染。

  useEffect(() => {
    if (innerVisible) {
      setInnerValue(selectedValue)
      setInnerOptions(options as PickerOptions[])
    }
-  }, [selectedValue, innerOptions, innerVisible])
+  }, [selectedValue, options, innerVisible])
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 9688104 and f81ef99.

📒 Files selected for processing (2)
  • src/packages/picker/picker.taro.tsx (7 hunks)
  • src/packages/picker/picker.tsx (6 hunks)
🧰 Additional context used
🪛 GitHub Check: codecov/patch
src/packages/picker/picker.tsx

[warning] 223-224: src/packages/picker/picker.tsx#L223-L224
Added lines #L223 - L224 were not covered by tests

⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: build
  • GitHub Check: test
🔇 Additional comments (7)
src/packages/picker/picker.taro.tsx (2)

192-215: 组件结构优化良好

将渲染逻辑抽取到 renderPickerElement 函数中是一个很好的做法,它使代码更加模块化和可读。使用 PickerView 替换旧的 PickerPanel 也使组件更加一致。


127-146: 结构化回调参数的良好实践

重构后的 onChangeItem 函数使用结构化参数对象是一个很好的模式,提高了代码的可读性和可维护性。使用 isEqual 来避免不必要的状态更新也是一个优化。

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

222-225: 为 onOverlayClick 处理器添加测试覆盖

静态分析工具显示这部分代码未被测试覆盖。需要添加单元测试来确保 closeOnOverlayClick 属性的正确行为。

#!/bin/bash
# 检查是否有现有测试覆盖这部分代码
rg -A 2 "onOverlayClick" --glob "**/__tests__/*.spec.tsx"
🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 223-224: src/packages/picker/picker.tsx#L223-L224
Added lines #L223 - L224 were not covered by tests


190-213: 模块化渲染函数的良好实践

将渲染逻辑抽取到 renderPickerElement 函数中是一个很好的做法,它使代码更加模块化和可读。这种重构提高了代码的可维护性。


26-51: 类型定义的改进

PickerOptionsPickerValue 类型替换旧的类型定义是一个很好的改进,提高了类型安全性。回调函数签名的更新也使得 API 更加一致和易于使用。


127-144: 结构化的参数处理

新的 onChangeItem 函数使用结构化参数和命名明确的回调参数,这使得代码更易于理解和维护。使用 isEqual 避免不必要的状态更新也是一个良好的优化。


228-228: SafeArea 组件缺少测试

新增的 SafeArea 组件使用缺少测试覆盖,建议添加相应的单元测试来确保其正确渲染。

@irisSong
Copy link
Collaborator Author

1、弹出时,没有动效了 2、建议默认有值被选中,参考线上 image 3、datepicker 平闰年处理:慢慢往上拖年份的时候会出现。 image

1、已修改 2、没有默认值就应该不选中,要不内外不一致 3、暂未复现,待复现再跟进修改

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 (2)
src/packages/picker/picker.taro.tsx (2)

121-126: useEffect 依赖项需优化

当前 useEffect 依赖数组包含 innerOptions,但效果体中没有使用它,这可能导致不必要的重新渲染。

建议移除不必要的依赖项:

- }, [selectedValue, innerOptions, innerVisible])
+ }, [selectedValue, innerVisible])

191-214: 渲染逻辑重构

renderPickerElement 函数封装了渲染逻辑,代码组织更加清晰:

  1. 使用新的 PickerView 组件替代旧的 PickerPanel
  2. 属性传递和回调处理更加直接

但在第200行,直接使用 props.options 而非之前解构的 options (含默认值),可能导致不一致。

- options={props.options}
+ options={options}
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between f81ef99 and f278479.

📒 Files selected for processing (1)
  • src/packages/picker/picker.taro.tsx (7 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: test
🔇 Additional comments (10)
src/packages/picker/picker.taro.tsx (10)

8-24: 导入模块的重构改进了组件架构

导入更改表明组件架构有显著改进:

  1. 从使用 PickerPanel 切换到 PickerView
  2. 引入更精确的类型定义如 PickerOptions, PickerValue
  3. 添加 isEqual 用于优化比较操作
  4. 引入 SafeArea 组件提升用户体验

这些变更使组件结构更清晰,类型定义更严格,有利于代码维护和类型安全。


29-36: Props 接口类型定义优化提升类型安全

接口定义的变更将通用数组类型替换为更具体的类型:

  • options: PickerOptions[] 替代旧的 (PickerOption | PickerOption[])[]
  • valuedefaultValue 使用 PickerValue[] 类型
  • 回调函数签名使用更明确的类型和参数结构,尤其是 onChange 使用了单一的 PickerOnChangeCallbackParameter 对象

这些改进有效增强了类型安全性,减少了潜在的类型错误,使 API 更加清晰。

Also applies to: 41-49


86-93: selectedValue 的处理方式改进

usePropsValue 钩子的使用和回调修改改进了值的处理流程:

  • 类型注解明确为 PickerValue[]
  • 回调中直接使用 selectedOptionsRef.current 传递给 onConfirm

这种方式与修改后的类型系统保持一致,但需确保 selectedOptionsRef 在初始渲染时已正确初始化。
[approve]


98-102: onClose 回调参数更新

闭包处理通过使用 selectedOptionsRef.currentinnerValue 作为回调参数,保持了与接口定义的一致性。这是一个好的改进,确保了组件关闭时能够传递正确的选中值。


115-119: 状态管理重构

状态管理的重构包括:

  1. 使用 useStateuseRef 跟踪 innerValue
  2. 类型明确的 innerOptions 状态
  3. 添加 selectedOptionsRef 引用持久化选中选项

这种方式更加稳健,可以在重渲染时保持一致性,尤其是针对回调函数的处理。


128-145: 变更处理逻辑优化

新的 onChangeItem 函数很好地封装了选项变更的处理逻辑:

  1. 维护 selectedOptionsRef 的当前状态
  2. 使用 isEqual 避免不必要的更新
  3. 更新 innerValueRef 和状态
  4. 条件性触发外部 onChange 回调

这种实现方式清晰明了,有效减少了冗余代码,同时优化了性能。


147-157: 确认和取消事件处理优化

onConfirmEventonCancelEvent 函数重构使逻辑更清晰:

  1. 确认事件中添加了移动检测,防止在滚动时意外确认
  2. 取消事件正确重置内部值到之前选中的值

这种实现改进了用户体验,避免了可能的错误操作。

Also applies to: 159-163


219-230: Popup 组件用法优化

Popup 处理的改进包括:

  1. 简化遮罩点击逻辑,直接调用 onCancelEvent
  2. 条件渲染提高性能,只在 innerVisible 为 true 时渲染内容
  3. 添加 SafeArea 组件改善移动设备体验

这些更改提升了组件的性能和用户体验。


235-235: 类型参数更新

React.forwardRef 中使用 PickerRef 替代 unknown 增强了类型安全性,使 ref 对象具有明确的类型定义,便于使用者了解可用的方法和属性。


8-236:

❓ Verification inconclusive

关于 PR 需求的验证

PR 评论中提到了 "Picker 弹出来没有动画",但当前代码中未明确解决此问题。Popup 组件应该提供动画效果,建议检查 Popup 组件的配置或考虑添加动画属性。

关于默认值选择的问题,当前实现以 selectedValue 初始化 innerValue,应该符合需求,但需确认没有默认值时的行为是否符合预期。

对于闰年日期选择器问题,本文件是 Picker 的基础实现,此问题可能需要在 DatePicker 组件中解决。


🌐 Web query:

React 组件中如何为弹出层添加动画效果的最佳实践

💡 Result:

在 React 组件中为弹出层添加动画效果时,最佳实践需要兼顾视觉效果与性能优化。以下是几种主流实现方案及核心要点:

一、CSS 过渡方案

通过 CSS transitiontransform 实现基础动画:

.modal {
  transition: transform 0.3s ease-out;
  transform: translateY(100%);
}
.modal.active {
  transform: translateY(0);
}

关键技巧

  • 使用 requestAnimationFrame 延迟激活状态确保 CSS 过渡生效[5]
  • 通过 opened 状态控制组件挂载时机[5]
const [opened, setOpened] = useState(false);
useEffect(() => {
  if (visible) {
    setOpened(true);
    requestAnimationFrame(() => setActive(true));
  }
}, [visible]);

二、React Animated API

适用于复杂时序控制的场景:

const fadeAnim = useRef(new Animated.Value(0)).current;
Animated.timing(fadeAnim, {
  toValue: 1,
  duration: 500,
  easing: Easing.bezier(0.4, 0, 0.2, 1),
}).start();

典型应用

  • Y轴位移动画结合插值计算[3]
translateY: offset.interpolate({
  inputRange: [0, 1],
  outputRange: [height, height - contentHeight]
})

三、第三方动画库(推荐)

react-spring 提供声明式动画方案:

const [maskStyle, contentStyle] = useSprings(2, [
  { opacity: visible ? 1 : 0 },
  { transform: `translateY(${visible ? '0%' : '100%'})` }
]);

优势特性

  • 自动处理生命周期与性能优化[7]
  • GPU加速的流畅动画效果[6]

四、关键优化策略

优化方向 实施方法
条件渲染 {isMounted && <Modal/>}
Portal挂载 createPortal(modalContent, document.body)
避免重渲染 React.memo() + shouldComponentUpdate
异步加载资源 const Modal = React.lazy(() => import('./Modal'))

五、进阶实践建议

  1. 复合动画控制:使用 Animated.parallel()/sequence()编排多元素协同运动[3]
  2. 无障碍支持:添加 role="dialog" + aria-modal="true" + ESC关闭支持[2][6]
  3. 弹性动效设计:采用弹簧物理模型替代线性缓动 (easing: Easing.bezier())[7]

通过合理选择技术方案并遵循这些实践原则,可在 React 应用中构建既流畅又稳定的弹层动效体系。[1][3][5][7]

Citations:


关于 Picker 弹层动画及默认值处理的建议

  • 目前在 Picker 弹层实现中未见明确的动画处理。建议检查 Popup 组件的配置,确认是否支持动画相关属性;如果没有,考虑采用 CSS 过渡、React Animated API 或 react-spring 等方案,为弹层添加平滑的过渡动画效果。
  • 默认值部分目前通过 selectedValue 初始化 innerValue,看上去符合预期,但请进一步确认当未提供默认值时组件的行为是否符合需求。
  • 关于闰年日期选择的问题,由于本文件实现的是基础 Picker 逻辑,相关逻辑应在 DatePicker 组件中处理,不在当前范围内。

@irisSong irisSong requested a review from xiaoyatong February 25, 2025 08:41
Copy link
Collaborator

@xiaoyatong xiaoyatong left a comment

Choose a reason for hiding this comment

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

picker 的 afterclose 方法,先暂时去掉,待有反馈再补充~

@xiaoyatong xiaoyatong merged commit 95dc4b8 into jdf2e:feat_v3.x Feb 27, 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
3 participants