【React】-组件中实现高性能鼠标跟随提示框的完整优化过程
🧠 组件中实现高性能鼠标跟随提示框的完整优化过程
在开发一个 PDF 阅读器组件时,我们常常需要实现一些交互功能,比如:在用户进行区域选择时,显示一个提示框跟随鼠标移动。这个看似简单的需求,在实际实现中却可能带来性能问题和视觉偏差。
本文将带你回顾我在开发 PDFViewBiz
组件过程中遇到的典型问题与解决思路,包括:
- 卡顿原因分析;
- 节流优化;
- 使用
requestAnimationFrame
控制更新频率; - 精准定位技巧;
- 从类组件到 Hook 模式的重构实践。
📌 一、需求背景
我们需要在用户开启“框选”模式时,显示一个提示信息框(如:“请在单据上拉框有问题的位置”),并让它始终跟随鼠标位置移动。
<div id="box1" ref={box1Ref} style={{ display: "none" }}>请在单据上拉框有问题的位置</div>
🚨 二、卡顿问题初现
最开始采用的是直接操作 DOM 的方式监听 mousemove
:
const mouseMoveEvent = (event) => {const box1 = box1Ref.current;if (!box1) return;const st = window.scrollY || document.documentElement.scrollTop;const sl = window.scrollX || document.documentElement.scrollLeft;box1.style.cssText = `left: ${event.clientX + sl}px;top: ${event.clientY + st}px;display: block;color: red;position: fixed;`;
};
虽然逻辑正确,但页面出现了严重卡顿,特别是在 PDF 页面滚动或缩放较大的情况下尤为明显。
🔍 三、卡顿原因分析
✅ 原因总结如下:
原因 | 描述 |
---|---|
mousemove 触发频率过高 | 每秒可达上百次,频繁触发重排重绘 |
直接操作 DOM 样式 | left、top 修改会强制浏览器重新布局 |
获取 scroll 值未优化 | 引起 Layout Thrashing(布局抖动) |
🛠️ 四、第一轮优化:节流处理
为了解决高频触发的问题,使用了 Lodash 的 throttle
:
import { throttle } from 'lodash-es';const mouseMoveEvent =