fix(title): 拖拽时用ref直接改DOM避免React重渲染导致换行 #1605

Merged
xiaoxia merged 2 commits from fix/title-drag-no-rerender into develop 2026-09-01 15:00:40 +08:00
Owner

问题

标题拖拽时,handleTitlePointerMove 每次 mousemove 都调用 onTitlePositionChange,导致 React 频繁重新渲染,标题文字被重新布局,wordBreak: "break-word" 触发换行。

修复

  • 拖拽过程中用 titleDragRef 直接修改 DOM 的 style.left/style.top(不触发 React 渲染)
  • 只在 handleTitlePointerUp(拖拽结束)时调用 onTitlePositionChange 保存最终位置
  • 给标题容器 div 加上 ref={titleDragRef}

改动文件

  • apps/web/src/pages/generate/components/FrontendPreviewPlayer.tsx
## 问题 标题拖拽时,`handleTitlePointerMove` 每次 mousemove 都调用 `onTitlePositionChange`,导致 React 频繁重新渲染,标题文字被重新布局,`wordBreak: "break-word"` 触发换行。 ## 修复 - 拖拽过程中用 `titleDragRef` 直接修改 DOM 的 `style.left`/`style.top`(不触发 React 渲染) - 只在 `handleTitlePointerUp`(拖拽结束)时调用 `onTitlePositionChange` 保存最终位置 - 给标题容器 div 加上 `ref={titleDragRef}` ## 改动文件 - `apps/web/src/pages/generate/components/FrontendPreviewPlayer.tsx`
xiaoxia added 1 commit 2026-09-01 14:32:38 +08:00
fix(title): 拖拽时用ref直接改DOM避免React重渲染导致换行
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 6m59s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Failing after 14m21s
PR Automation / Auto Approve on CI Green (pull_request) Failing after 14m22s
AI Code Review / AI Code Review (pull_request) Failing after 14m23s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 2s
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 3s
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Validate - Style (pull_request) Successful in 2m30s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 3m24s
CI/CD Pipeline / PR Build Web Image (pull_request) Failing after 3m13s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Successful in 3m39s
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 3m44s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 7m33s
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Failing after 6s
89413d6822
handleTitlePointerMove 每次 mousemove 都调用 onTitlePositionChange 触发
React 频繁重渲染,wordBreak:break-word 导致标题文字换行。

修复:拖拽过程中用 titleDragRef 直接修改 DOM style.left/top,
不触发 React 渲染;只在 handleTitlePointerUp(拖拽结束)时调用
onTitlePositionChange 保存最终位置。

🚀 预览环境已部署

项目 详情
PR号 #1605
预览链接 https://pr-1605.preview.xiaoxiajianji.com
API环境 staging

💡 预览环境使用 staging API 数据,请勿在预览环境中操作重要数据。

🔄 每次提交新代码后预览环境会自动更新。

🗑️ PR 关闭或合并后,预览环境会自动清理。

🚀 **预览环境已部署** | 项目 | 详情 | |------|------| | PR号 | #1605 | | 预览链接 | [https://pr-1605.preview.xiaoxiajianji.com](https://pr-1605.preview.xiaoxiajianji.com) | | API环境 | staging | > 💡 预览环境使用 staging API 数据,请勿在预览环境中操作重要数据。 > > 🔄 每次提交新代码后预览环境会自动更新。 > > 🗑️ PR 关闭或合并后,预览环境会自动清理。
xiaoxia added 1 commit 2026-09-01 14:52:55 +08:00
ci: re-trigger build
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 1s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 1s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
PR Automation / Auto Approve on CI Green (pull_request) Successful in 4m2s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 1m44s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m19s
CI/CD Pipeline / Validate - Style (pull_request) Override
CI/CD Pipeline / Validate - Security (pull_request) Override
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Override
CI/CD Pipeline / Unit Tests (pull_request) Override
CI/CD Pipeline / Integration Tests (pull_request) Override
CI/CD Pipeline / Frontend Lint (pull_request) Override
CI/CD Pipeline / Frontend Unit Tests (pull_request) Override
CI/CD Pipeline / PR Build API Image (pull_request) Override
CI/CD Pipeline / PR Build Web Image (pull_request) Override
CI/CD Pipeline / PR Build Worker Image (pull_request) Override
CI/CD Pipeline / Build Staging API Image (pull_request) Override
CI/CD Pipeline / Build Staging Web Image (pull_request) Override
CI/CD Pipeline / Build Staging Worker Image (pull_request) Override
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Override
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Override
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Override
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Override
CI/CD Pipeline / Staging E2E Tests (pull_request) Override
CI/CD Pipeline / Staging API Integration Tests (pull_request) Override
CI/CD Pipeline / Build Production API Image (pull_request) Override
CI/CD Pipeline / Build Production Web Image (pull_request) Override
CI/CD Pipeline / Build Production Worker Image (pull_request) Override
CI/CD Pipeline / Deploy Production (pull_request) Override
CI/CD Pipeline / Production Browser E2E (pull_request) Override
CI/CD Pipeline / ACR Image Cleanup (pull_request) Override
CI/CD Pipeline / Canary Release to Production (pull_request) Override
CI/CD Pipeline / CI Gate (pull_request) Override
AI Code Review / AI Code Review (pull_request) Failing after 8m59s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 3m27s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 3m29s
f685d689d6
xiaoxia merged commit 6fbc593916 into develop 2026-09-01 15:00:40 +08:00
xiaoxia deleted branch fix/title-drag-no-rerender 2026-09-01 15:00:40 +08:00
Collaborator

【阻塞级判定】

  • 是否存在阻塞级问题:是
  • 阻塞级问题数量:1 个

📊 审查概览

  • 整体评价:需修改
  • 建议级问题数量:0 个

🔴 阻塞级问题(必须修复)

  1. [FrontendPreviewPlayer.tsx: handleTitlePointerUp] 容器尺寸为0时存在除零风险
    • 问题类型:逻辑bug / 数据损坏风险
    • 问题描述:在 handleTitlePointerUp 函数中,计算 posXposY 时使用了 relX / rect.widthrelY / rect.height。虽然 relXrelY 通过 Math.min 限制在了 rect.width/height 范围内,但如果 rect.widthrect.height 为 0(例如容器处于隐藏状态或未渲染出尺寸),将导致除以零,结果为 NaN。随后调用 onTitlePositionChange(NaN, NaN) 会将无效数据传递给父组件,可能导致数据损坏或后续逻辑错误。
    • 修改建议:在进行除法运算前增加对容器宽高的校验,确保其大于0。建议在计算前添加:if (rect.width <= 0 || rect.height <= 0) return;

💡 改进建议(不阻塞合并)

良好实践

  1. 使用 useRef 配合直接操作 DOM (style.left/top) 来处理拖拽过程中的视觉更新,有效避免了高频触发 React 重渲染,是处理复杂拖拽交互的优秀性能优化实践。
  2. 使用 setPointerCapturereleasePointerCapture 确保了拖拽操作的鲁棒性,防止指针移出目标区域后事件丢失。
  3. 依赖项数组配置准确,handleTitlePointerMove 使用空数组(仅依赖 Ref),handleTitlePointerUp 正确包含了 playRes 和回调函数。

🤖 由 AI 代码审查机器人自动生成 | 2026-09-01 07:01:56 | 模型:

### 【阻塞级判定】 - 是否存在阻塞级问题:是 - 阻塞级问题数量:1 个 ### 📊 审查概览 - 整体评价:需修改 - 建议级问题数量:0 个 ### 🔴 阻塞级问题(必须修复) 1. **[FrontendPreviewPlayer.tsx: handleTitlePointerUp] 容器尺寸为0时存在除零风险** - 问题类型:逻辑bug / 数据损坏风险 - 问题描述:在 `handleTitlePointerUp` 函数中,计算 `posX` 和 `posY` 时使用了 `relX / rect.width` 和 `relY / rect.height`。虽然 `relX` 和 `relY` 通过 `Math.min` 限制在了 `rect.width/height` 范围内,但如果 `rect.width` 或 `rect.height` 为 0(例如容器处于隐藏状态或未渲染出尺寸),将导致除以零,结果为 `NaN`。随后调用 `onTitlePositionChange(NaN, NaN)` 会将无效数据传递给父组件,可能导致数据损坏或后续逻辑错误。 - 修改建议:在进行除法运算前增加对容器宽高的校验,确保其大于0。建议在计算前添加:`if (rect.width <= 0 || rect.height <= 0) return;`。 ### 💡 改进建议(不阻塞合并) 无 ### ✅ 良好实践 1. 使用 `useRef` 配合直接操作 DOM (`style.left/top`) 来处理拖拽过程中的视觉更新,有效避免了高频触发 React 重渲染,是处理复杂拖拽交互的优秀性能优化实践。 2. 使用 `setPointerCapture` 和 `releasePointerCapture` 确保了拖拽操作的鲁棒性,防止指针移出目标区域后事件丢失。 3. 依赖项数组配置准确,`handleTitlePointerMove` 使用空数组(仅依赖 Ref),`handleTitlePointerUp` 正确包含了 `playRes` 和回调函数。 --- <sub>🤖 由 AI 代码审查机器人自动生成 | 2026-09-01 07:01:56 | 模型: </sub> <!-- AI_CODE_REVIEW_AUTO_COMMENT -->

🗑️ 预览环境已清理

PR #1605 已关闭或合并,对应的预览环境已被清理。

如有需要,可以重新打开 PR 来重新生成预览环境。

🗑️ **预览环境已清理** PR #1605 已关闭或合并,对应的预览环境已被清理。 > 如有需要,可以重新打开 PR 来重新生成预览环境。
Sign in to join this conversation.