forked from mengyxu/noob-components
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
121 lines
4.5 KiB
121 lines
4.5 KiB
|
3 months ago
|
# Plan: Viewport Resize Handling for list-table-v2
|
||
|
|
|
||
|
|
## 1. Problem Analysis
|
||
|
|
|
||
|
|
### Current State
|
||
|
|
- The `list-table-v2` component uses a probe row technique to dynamically measure row height when `rowHeight` is NOT explicitly set (dynamic height mode)
|
||
|
|
- The `measureProbeRow` function (lines 217-231) already exists and correctly:
|
||
|
|
- Clears `estimatedRowHeight.value` before re-measuring
|
||
|
|
- Uses TWO `requestAnimationFrame` calls after `nextTick` to let el-table-v2 fully settle
|
||
|
|
- Measures the probe row's `offsetHeight`
|
||
|
|
|
||
|
|
### Problem
|
||
|
|
- When the viewport width changes, column widths may adjust (due to `flexGrow: 1` in `tableColumns` computed)
|
||
|
|
- This can cause row heights to change, but currently there is no trigger to re-measure
|
||
|
|
- Without re-measuring, the `estimatedRowHeight` may become inaccurate, causing layout issues
|
||
|
|
|
||
|
|
### Constraints (from previous attempts)
|
||
|
|
1. ResizeObserver on container caused errors in component setup - AVOID
|
||
|
|
2. Must use TWO `requestAnimationFrame` calls after `nextTick` for proper el-table-v2 settlement
|
||
|
|
3. Must clear `estimatedRowHeight` before re-measuring for el-table-v2 to recalculate properly
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 2. Implementation Approach
|
||
|
|
|
||
|
|
### Strategy
|
||
|
|
Add a debounced window resize event listener that:
|
||
|
|
1. Checks if dynamic height mode is active (`shouldUseProbeRow`)
|
||
|
|
2. Calls the existing `measureProbeRow` function
|
||
|
|
3. Cleans up properly on component unmount
|
||
|
|
|
||
|
|
### Why Window Resize Instead of ResizeObserver
|
||
|
|
- `el-auto-resizer` already handles container size changes internally
|
||
|
|
- Window resize is the correct trigger because column widths change based on viewport width (via `flexGrow`)
|
||
|
|
- ResizeObserver on container caused setup errors in previous attempts
|
||
|
|
|
||
|
|
### Debounce Strategy
|
||
|
|
- Use lodash's `debounce` (already imported as `lodash-es`)
|
||
|
|
- Debounce delay: ~200-300ms to avoid excessive recalculations during active resize
|
||
|
|
- The debounced function will be created with `onMounted` and cleaned up with `onUnmounted`
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 3. Code Changes Needed
|
||
|
|
|
||
|
|
### File: `/home/hechang27/Documents/sprt/noob-components/packages/base/data/list-table-v2.vue`
|
||
|
|
|
||
|
|
#### Import Additions (line 53)
|
||
|
|
```typescript
|
||
|
|
import { ref, computed, watch, h, onMounted, onUpdated, onUnmounted, useSlots, renderSlot, nextTick } from "vue";
|
||
|
|
```
|
||
|
|
|
||
|
|
#### New State Variable
|
||
|
|
After line 66 (`const estimatedRowHeight = ref<number | undefined>(undefined);`):
|
||
|
|
```typescript
|
||
|
|
// Debounced resize handler for re-measuring probe row
|
||
|
|
const debouncedResizeHandler = ref<() => void>();
|
||
|
|
```
|
||
|
|
|
||
|
|
#### New Lifecycle Hooks
|
||
|
|
After line 214 (after the existing `watch` block):
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// Setup resize listener on mount
|
||
|
|
onMounted(() => {
|
||
|
|
// Create debounced handler
|
||
|
|
debouncedResizeHandler.value = lodash.debounce(() => {
|
||
|
|
// Only re-measure in dynamic height mode
|
||
|
|
if (shouldUseProbeRow.value) {
|
||
|
|
measureProbeRow();
|
||
|
|
}
|
||
|
|
}, 250); // 250ms debounce delay
|
||
|
|
|
||
|
|
// Attach window resize listener
|
||
|
|
window.addEventListener('resize', debouncedResizeHandler.value);
|
||
|
|
});
|
||
|
|
|
||
|
|
// Cleanup on unmount
|
||
|
|
onUnmounted(() => {
|
||
|
|
if (debouncedResizeHandler.value) {
|
||
|
|
window.removeEventListener('resize', debouncedResizeHandler.value);
|
||
|
|
debouncedResizeHandler.value.cancel(); // Cancel any pending debounce calls
|
||
|
|
}
|
||
|
|
});
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 4. Verification Steps
|
||
|
|
|
||
|
|
### Manual Testing
|
||
|
|
1. Open a page using `list-table-v2` without explicit `rowHeight` prop
|
||
|
|
2. Open browser DevTools and inspect a row element to see its height
|
||
|
|
3. Resize the browser window (change width)
|
||
|
|
4. Verify that:
|
||
|
|
- No console errors occur during resize
|
||
|
|
- The row height is recalculated correctly after resize settles
|
||
|
|
- The table layout remains correct after resize
|
||
|
|
|
||
|
|
### Edge Cases to Verify
|
||
|
|
1. **Rapid resize**: Resize window quickly back and forth - should not cause errors or excessive measurements
|
||
|
|
2. **Minimum width**: Table should handle minimum width gracefully without breaking
|
||
|
|
3. **No explicit rowHeight**: Verify resize handling is NOT active when `rowHeight` IS set (fixed height mode)
|
||
|
|
4. **Unmount cleanup**: Navigate away from the page and verify no memory leaks or hanging listeners
|
||
|
|
|
||
|
|
### Code Review Checklist
|
||
|
|
- [ ] `onUnmounted` is imported and used
|
||
|
|
- [ ] Debounced handler is properly cancelled on unmount
|
||
|
|
- [ ] `shouldUseProbeRow.value` check prevents unnecessary calls in fixed-height mode
|
||
|
|
- [ ] Two RAF frames are used in `measureProbeRow` (existing pattern preserved)
|
||
|
|
- [ ] `estimatedRowHeight` is cleared before re-measuring (existing pattern preserved)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 5. Dependencies
|
||
|
|
|
||
|
|
- lodash-es debounce (already imported)
|
||
|
|
- Vue lifecycle hooks (already available)
|
||
|
|
|
||
|
|
No new dependencies required.
|