React应用多次点击随机移动按钮后页面卡顿如何优化
卡顿核心原因
- 最根本的问题是
useEffect没有指定依赖数组,每次组件重渲染都会新增一个mousemove事件监听器:你每点击一次按钮调用setchange就会触发组件重渲染,相当于每次点击都多绑定了一个鼠标移动监听函数,点击次数多了后,鼠标移动一次会触发成百上千个回调同时执行,直接导致页面卡顿。 - 存在冗余的重复操作:你既用
change状态控制绿色方块的left属性,又直接通过EN的ref修改style.left,而且样式里的left: "${change}px"写法错误(用了双引号而非反引号,模板字符串根本没生效),change状态完全没用,反而导致了不必要的组件重渲染。 - 鼠标移动回调存在大量无效操作:同时修改元素的
top/bottom/left/right四个定位属性,实际上只需要改left和top即可,再加高频触发的console.log也会额外占用性能。 - 随机数生成逻辑位置错误:
randomize变量定义在组件顶层,只有组件重渲染时才会生成新的随机值,多次点击按钮用的是同一个随机数,不符合随机移动的预期。
修复方案
- 给
useEffect添加空依赖数组,保证全局只绑定一次mousemove监听器,同时添加清理函数在组件卸载时移除监听器,避免内存泄漏。 - 删掉没用的
change状态和对应的setchange调用,避免不必要的组件重渲染,直接通过ref操作绿色方块位置即可。 - 优化
mousemove回调逻辑,删掉无效的属性修改和console.log语句。 - 把随机数生成逻辑移到
enem函数内部,保证每次点击都生成新的随机位置。 - 把固定不变的样式对象移到组件外部,避免每次渲染重复创建对象。
修正后完整代码
const { useRef, useEffect } = React // 固定样式移到组件外,避免重复创建 const cursors = { pointerEvents: "none", borderRadius: "50%", width: "20PX", height: "20PX", backgroundColor: "red", position: "fixed", transform:"translate3d(-10px,-10px,15px)", }; const enemy = { zIndex: "-1", borderRadius: "20%", width: "30PX", height: "30PX", backgroundColor: "green", position: "absolute", left: "1px", }; const borders = { width: "1300px", height: "620px", background: "#ccc", border: "4px solid #333", position: "absolute", right: "500px" } const Main = props => { const textInput = useRef() const EN = useRef() const move = useRef() function enem() { // 随机数移到函数内部,每次点击生成新值 const randomize = Math.floor(Math.random() * 1320) EN.current.style.left = randomize + "px" } useEffect(() => { // 提取监听函数,方便后续移除 const handleMouseMove = (event) =>{ textInput.current.style.top = event.clientY + 'px' textInput.current.style.left = event.clientX + 'px' } document.addEventListener("mousemove", handleMouseMove) // 添加清理函数,卸载时移除监听 return () => document.removeEventListener("mousemove", handleMouseMove) }, []); // 空依赖数组,仅执行一次 return ( <div style={borders} > <div ref={textInput} style={cursors}></div> <div style={enemy} ref={EN}></div> <div className={"pe"} ref={move}></div> <button onClick={enem}>Move randomly</button> </div> ) } ReactDOM.render(<Main />, document.getElementById("root"));
内容的提问来源于stack exchange,提问作者eddie delgatto
相关产品推荐
相关产品推荐

