-
-
Notifications
You must be signed in to change notification settings - Fork 607
feat: support column.resizable #1106
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
base: master
Are you sure you want to change the base?
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
02c41ed
to
0eab6c4
Compare
体验有点怪异,如果是超出 width 的时候缩小应该就是缩小,不应该把右边的撑开才对。 |
6ad31d3
to
c50f2da
Compare
c50f2da
to
97d5903
Compare
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## master #1106 +/- ##
==========================================
+ Coverage 97.96% 98.06% +0.09%
==========================================
Files 51 53 +2
Lines 4674 4913 +239
Branches 597 627 +30
==========================================
+ Hits 4579 4818 +239
Misses 91 91
Partials 4 4 ☔ View full report in Codecov by Sentry. |
mark |
mark 2 |
冲突了 |
## Walkthrough
本次更改为表格组件引入了列宽可调整(resizable)功能。更新内容涵盖了接口、上下文、样式、文档、示例和测试,支持通过拖拽表头实现列宽调整,并在状态变更时触发回调。相关钩子、属性和上下文均已适配,增加了最小宽度限制和视觉反馈。
## Changes
| 文件/路径 | 变更摘要 |
|-------------------------------------------|----------------------------------------------------------------------------------------------------------------------|
| README.md | 文档新增 `resizable` 列属性说明。 |
| assets/index.less | 新增列宽调整相关样式,包括拖拽手柄、调整线和指针样式,修正固定列阴影的 pointer-events。 |
| docs/examples/column-resize.tsx | 示例重构为函数组件,移除 `react-resizable`,直接用内部列宽管理和拖拽回调,增加 RTL 切换和更丰富的数据。 |
| package.json | 移除 `react-resizable` 依赖。 |
| src/Body/MeasureCell.tsx<br>src/Body/MeasureRow.tsx<br>src/Body/index.tsx<br>src/VirtualTable/BodyGrid.tsx | 统一将 `onColumnResize` 重命名为 `onColumnWidthChange`,保持回调命名一致。 |
| src/FixedHolder/index.tsx | 监听滚动事件的 effect 增加 `direction` 依赖,确保方向变更时重新绑定。 |
| src/Header/HeaderCell.tsx | 新增 `HeaderCell` 组件,支持渲染可调整宽度的表头单元格,集成拖拽手柄。 |
| src/Header/HeaderRow.tsx | 表头行渲染由 `Cell` 改为 `HeaderCell`,增加可调整宽度、最小宽度等属性传递。 |
| src/Header/useCellResize.tsx | 新增 `useCellResize` 钩子,封装列宽拖拽逻辑、视觉反馈及事件处理。 |
| src/Table.tsx | Table 组件新增 `onColumnResizeEnd` 属性,扩展上下文传递列宽、拖拽状态及相关回调。 |
| src/context/TableContext.tsx | TableContextProps 扩展,增加列宽、拖拽状态、回调等属性,重命名相关方法。 |
| src/interface.ts | `ColumnType` 新增 `resizable` 属性,`CellType` 增加 `scrollbar` 标志。 |
| tests/Resizable.spec.tsx | 新增表格列宽调整功能的测试用例,覆盖宽度变更、最小宽度约束及回调验证。 |
## Sequence Diagram(s)
```mermaid
sequenceDiagram
participant User
participant HeaderCell
participant useCellResize
participant TableContext
participant Table
User->>HeaderCell: 按下拖拽手柄
HeaderCell->>useCellResize: 触发拖拽逻辑
useCellResize->>TableContext: 更新列宽状态
useCellResize-->>User: 拖拽视觉反馈
User->>useCellResize: 松开鼠标
useCellResize->>TableContext: 调用 onColumnResizeEnd
TableContext->>Table: 触发 onColumnResizeEnd 回调 Suggested reviewers
Poem
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Nitpick comments (7)
README.md (1)
136-136
: 清晰地记录了新的resizable属性文档中添加了列属性
resizable
的说明,使开发者能够了解列宽可调整的功能。不过,描述信息相对简单,建议扩展说明以包含更多详情,例如:
- 与
minWidth
属性的交互关系- 调整列宽的行为描述(根据PR评论中提到的用户体验问题)
- 可能的使用限制
-| resizable | Boolean | | column resize | +| resizable | Boolean | | Enable column resize functionality. When enabled, users can drag the edge of the column header to adjust its width. Works in conjunction with `minWidth` to control minimum column width. |src/Header/useCellResize.tsx (4)
59-60
: 删除遗留调试日志,避免污染生产环境
console.log
会在生产包中留下无意义的输出,既影响性能也影响日志可读性。建议在合并前移除或用受控的debug
方案替代。- console.log('colsWidths', colsWidths); … - console.log('componentWidth', componentWidth);Also applies to: 90-91
55-67
: 高频mousemove
回调建议节流/合并更新
onResize
在拖拽过程中会非常高频地触发,每次都会setLineLeft
引发组件重渲染,可能导致卡顿。可考虑:
- 使用
requestAnimationFrame
将更新合并到下一帧;- 或使用 lodash/throttle 节流;
- 亦可通过
useRef
直接操作 DOM,待mouseup
时再一次性setState
。
48-52
: 事件清理函数健壮性可提升
mouseMoveRef.current
初始为null
时直接传给removeEventListener
等同于传入null
,不同浏览器实现略有差异。可加判空保护,示例:- document.body.removeEventListener('mousemove', mouseMoveRef.current); - document.body.removeEventListener('mouseup', mouseUpRef.current); + mouseMoveRef.current && document.body.removeEventListener('mousemove', mouseMoveRef.current); + mouseUpRef.current && document.body.removeEventListener('mouseup', mouseUpRef.current);
115-118
: 监听目标与选项需再确认
目前把事件加到document.body
上,当鼠标移出窗口或在不同 iframe 中拖拽时可能丢失事件。通常将监听器注册到window
更稳妥:- document.body.addEventListener('mousemove', onResize); - document.body.addEventListener('mouseup', onResizeEnd); + window.addEventListener('mousemove', onResize); + window.addEventListener('mouseup', onResizeEnd);同时可加
{ capture: true }
或{ passive: false }
以避免默认行为。请确认兼容性需求后决定。tests/Resizable.spec.tsx (1)
58-60
: 伪造计时器后需恢复,避免串扰其它用例
vi.useFakeTimers()
会影响后续 test 文件,建议在afterEach
或afterAll
调用vi.useRealTimers()
,确保测试隔离。docs/examples/column-resize.tsx (1)
70-76
:parseInt
结果可能为NaN
,需提供默认值
当borderInlineStartWidth
为空字符串时parseInt
返回NaN
,后续计算会导致列宽为NaN
。可做兜底:- const mergedWidth = width - parseInt(borderWidth, 10); + const mergedWidth = width - (parseInt(borderWidth, 10) || 0);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (16)
README.md
(1 hunks)assets/index.less
(3 hunks)docs/examples/column-resize.tsx
(1 hunks)package.json
(0 hunks)src/Body/MeasureCell.tsx
(1 hunks)src/Body/MeasureRow.tsx
(2 hunks)src/Body/index.tsx
(3 hunks)src/FixedHolder/index.tsx
(1 hunks)src/Header/HeaderCell.tsx
(1 hunks)src/Header/HeaderRow.tsx
(3 hunks)src/Header/useCellResize.tsx
(1 hunks)src/Table.tsx
(9 hunks)src/VirtualTable/BodyGrid.tsx
(3 hunks)src/context/TableContext.tsx
(2 hunks)src/interface.ts
(2 hunks)tests/Resizable.spec.tsx
(1 hunks)
💤 Files with no reviewable changes (1)
- package.json
🧰 Additional context used
🧬 Code Graph Analysis (6)
src/Header/HeaderRow.tsx (1)
src/interface.ts (1)
ColumnType
(108-124)
src/Header/HeaderCell.tsx (3)
src/Cell/index.tsx (1)
CellProps
(19-58)src/interface.ts (1)
Key
(21-21)src/Header/useCellResize.tsx (1)
useCellResize
(7-153)
src/Body/MeasureRow.tsx (2)
src/interface.ts (1)
Key
(21-21)src/Body/MeasureCell.tsx (2)
MeasureCellProps
(5-8)MeasureCell
(10-26)
src/Body/MeasureCell.tsx (2)
src/interface.ts (1)
Key
(21-21)src/Body/MeasureRow.tsx (1)
MeasureCellProps
(6-10)
src/context/TableContext.tsx (1)
src/interface.ts (1)
Key
(21-21)
src/Header/useCellResize.tsx (1)
src/interface.ts (1)
Key
(21-21)
🔇 Additional comments (29)
src/FixedHolder/index.tsx (1)
112-112
: 修复方向变更导致的滚动计算错误问题这个修改解决了一个潜在的bug,在
useEffect
依赖数组中添加了direction
。由于effect内部逻辑(92-98行)使用了direction
变量来计算滚动行为,如果这个属性在组件挂载后动态改变,没有这个依赖项会导致滚动方向逻辑不正确。修改后,当
direction
属性变化时,事件监听器会被正确地移除和重新添加,确保使用最新的方向值进行滚动计算。src/Body/index.tsx (1)
28-28
: 属性命名更改,使其更具描述性将
onColumnResize
重命名为onColumnWidthChange
是一个好的改进,更准确地反映了此回调的用途 - 它在列宽度变化时被调用,而不仅仅是在调整大小操作期间。这个更改在整个代码库中保持一致,使API更加直观且符合其实际功能。
Also applies to: 37-37, 106-106
src/VirtualTable/BodyGrid.tsx (1)
26-26
:✅ Verification successful
属性命名更改,使其更具描述性
同样,在
VirtualTable/BodyGrid.tsx
中也将onColumnResize
重命名为onColumnWidthChange
,保持了整个代码库的一致性。这个命名更好地描述了此回调的实际功能 - 在列宽度发生变化时通知相关组件。Also applies to: 35-35, 73-73
🏁 Script executed:
#!/bin/bash # 检查代码库中是否还有其他的onColumnResize未被替换,确保命名一致性 echo "检查是否还有任何遗漏的onColumnResize引用:" rg "onColumnResize" --type=typescript --type=tsxLength of output: 294
下面
rg
的--type=typescript
无效,我们改用扩展名过滤重新搜索:
🏁 Script executed:
#!/bin/bash echo "再次检查是否还有遗漏的 onColumnResize 引用:" rg "onColumnResize" -n -g '*.ts' -g '*.tsx'Length of output: 1757
已验证命名一致性,无残留 onColumnResize 引用
已确认onColumnResize
已全部替换为onColumnWidthChange
,代码库中无残留引用,命名保持一致,建议批准此次更新。src/interface.ts (2)
56-56
: 表格结构中添加了滚动条标记通过在
CellType
接口的column
属性中添加可选的scrollbar
布尔标志,使单元格能够携带滚动条存在的元数据信息。这一改进有助于在HeaderRow
中识别靠近滚动条的单元格,从而确保正确处理列宽调整功能。
120-120
: 新增列宽可调整功能为
ColumnType
接口添加了新的可选布尔属性resizable
,用于指示列是否支持调整大小。这与 PR 标题中提到的"feat: columnResizable"功能相符,为表格组件提供了重要的交互增强。src/Header/HeaderRow.tsx (4)
13-13
: 导入专用表头单元格组件从通用的
Cell
组件切换到专用的HeaderCell
组件导入,提高了代码的可读性和组件的专业化程度。这种变化符合关注点分离的原则,为表头单元格提供了更专业的实现。
62-64
: 添加滚动条前单元格检测逻辑添加了逻辑来确定单元格是否位于滚动条前面。这对于正确处理调整大小的行为至关重要,特别是在滚动条附近的单元格,确保用户体验的一致性。
67-67
: 使用专用的表头单元格组件从通用的
Cell
组件切换到专用的HeaderCell
组件,与第13行的导入变更相对应。
78-81
: 传递额外的列调整属性向
HeaderCell
组件传递了重要的额外属性:
columnKey
:列的唯一标识符isScrollBarPreviousCell
:指示此单元格是否位于滚动条之前resizable
:确定列是否可调整大小(对于滚动条列设置为 false)minWidth
:列的最小宽度这些属性的传递确保了列宽调整功能的正确实现,特别是对于边缘情况(如滚动条附近的单元格)的处理。
src/Body/MeasureCell.tsx (3)
7-7
: 更新回调函数名称以提高描述性将属性从
onColumnResize
重命名为onColumnWidthChange
,使其更准确地描述回调函数的目的和行为。这符合 PR 目标中提到的"重命名内部事件处理程序以更好地区分其目的"。
10-10
: 更新参数解构以匹配新的属性名对函数参数解构进行相应更新,以使用新的属性名
onColumnWidthChange
。这与第7行的接口变更保持一致。
15-15
: 更新回调函数调用将回调函数调用从
onColumnResize
更新为onColumnWidthChange
,保持了API的一致性,同时提高了代码的可读性和可维护性。src/Body/MeasureRow.tsx (4)
8-8
: 更新接口中的回调函数名称将
MeasureCellProps
接口中的属性从onColumnResize
更新为onColumnWidthChange
,使其更准确地描述回调的目的。这与MeasureCell
组件中的更改保持一致,确保了整个代码库中命名的一致性。
12-16
: 更新函数参数解构更新组件参数解构以使用新的属性名
onColumnWidthChange
,确保与接口定义保持一致。这种改变简单明了,保持了代码的一致性。
30-30
: 更新批量调整大小回调中的函数调用在
onBatchResize
处理函数中,将回调函数调用从onColumnResize
更新为onColumnWidthChange
,保持了API的一致性。
36-40
: 更新传递给 MeasureCell 的属性将传递给
MeasureCell
子组件的属性从onColumnResize
更新为onColumnWidthChange
,确保与子组件接口的一致性。这完成了组件树中属性传递的一致性更改。assets/index.less (2)
58-60
: 添加列宽调整时的光标样式新增的
column-resizing
类可以在用户调整列宽时提供视觉反馈,设置鼠标为col-resize
光标。这种交互设计符合用户期望。
102-102
: 防止阴影元素干扰鼠标事件添加
pointer-events: none
可以确保阴影元素不会干扰用户的鼠标交互,这是一个很好的改进。src/Header/HeaderCell.tsx (2)
1-12
: 组件接口设计合理新增的
HeaderCell
组件接口设计合理,扩展了CellProps
并添加了与列宽调整相关的必要属性。特别是resizable
属性用于控制是否允许调整列宽,minWidth
用于限制最小宽度,这些设计很好地支持了列宽调整功能。
13-30
: 实现简洁且功能完整组件实现逻辑清晰:
- 从 props 中提取与列宽调整相关的属性
- 调用
useCellResize
钩子生成调整手柄节点- 通过
appendNode
属性将调整手柄附加到基础Cell
组件这种实现方式保持了原有
Cell
组件的所有功能,同时优雅地添加了列宽调整能力。src/context/TableContext.tsx (2)
60-60
: 更准确的回调函数命名将
onColumnResize
更名为onColumnWidthChange
使其名称更加准确地反映了其功能 - 在列宽发生变化时触发回调。这符合 PR 的目标,使命名更加明确。
73-82
: 增加必要的上下文属性支持列宽调整功能新增的上下文属性合理且必要,用于支持列宽调整功能:
fullTableRef
: 引用完整表格元素,用于定位调整线colsWidths
、colWidths
、colsKeys
: 跟踪列宽信息onColumnResizeEnd
: 提供列宽调整结束时的详细信息onResizingChange
: 通知调整状态变化这些属性共同构成了完整的列宽调整功能所需的状态和回调机制。
src/Table.tsx (7)
129-133
: 添加列宽调整结束回调接口新增的
onColumnResizeEnd
回调提供了丰富的信息,包括调整后的列键、宽度以及所有列的宽度信息。这种设计允许消费者在列宽调整完成时执行必要的操作,增强了组件的可用性。
359-359
: 跟踪列宽调整状态添加
isResizing
状态可以跟踪列宽是否正在调整中,这对于提供视觉反馈和限制某些操作很有用。
363-364
: 优化列键的记忆化逻辑使用
join('_')
作为依赖项来记忆化colsKeys
是一种优化方式,但需要注意列键中如果包含下划线可能导致意外的记忆化失效。请考虑使用不太可能出现在列键中的分隔符,或使用其他记忆化策略:
- const colsKeys = React.useMemo(() => pureColsKeys, [pureColsKeys.join('_')]); + const colsKeys = React.useMemo(() => pureColsKeys, [pureColsKeys.join('|')]);或者考虑使用更可靠的方式比较数组内容。
413-422
: 更新回调函数命名,保持一致性将
onColumnResize
改为onColumnWidthChange
,与上下文中的命名保持一致,增强了代码的可读性和可维护性。实现逻辑保持不变,仅是命名更新。
795-795
: 添加调整时的样式类当列宽调整进行时,添加
rc-table-column-resizing
类可以改变光标样式,提供视觉反馈,这与 CSS 文件中定义的样式配合良好。
866-872
: 完善上下文值,支持列宽调整功能扩展
TableContextValue
以包含所有与列宽调整相关的属性和回调,这确保了子组件可以访问所需的信息来实现列宽调整功能。
909-913
: 更新依赖数组,确保上下文适当更新依赖数组中增加了新的列宽调整相关属性,确保当这些值变化时上下文会重新计算,这对于维护组件的正确行为至关重要。
看看 ai 的 review |
没问题,在对应的下面回复了,命名的话要改也可以改 |
document.body.addEventListener('mousemove', onResize); | ||
document.body.addEventListener('mouseup', onResizeEnd); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
start 前也可以先卸载一下。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
end 时、组件 unmount 的时候都有卸载了。start 前要卸载是什么情况下需要?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
我担心一些情况下未触发 onDragEnd,比如拖到屏幕外 or iframe 外?
@@ -133,6 +133,7 @@ React.render(<Table columns={columns} data={data} />, mountNode); | |||
| fixed | String \| Boolean | | this column will be fixed when table scroll horizontally: true or 'left' or 'right' | | |||
| align | String | | specify how cell content is aligned | | |||
| ellipsis | Boolean | | specify whether cell content be ellipsized | | |||
| resizable | Boolean | | column resize | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| resizable | Boolean | | column resize | | |
| resizable | Boolean | | set column to be resizable | |
原先内部
onColumnResize
重命名为onColumnWidthChange
,进行区分Summary by CodeRabbit