ReactJS实现随鼠标位置调整Div宽度并添加防抖延迟
解决React中鼠标移动频繁触发渲染的问题
嘿,这个场景太常见啦!鼠标移动事件触发频率超高,每次都调用setState确实会让组件反复渲染,既浪费性能又没必要。咱们可以用**防抖(Debounce)**机制来搞定——它的核心逻辑就是:让目标函数在最后一次触发后的指定延迟时间才执行,这样就能把连续的鼠标事件合并成一次更新,大大减少渲染次数。
下面结合你的代码,给你两种实用方案:
方案一:手写防抖函数(无需额外依赖)
先自己实现一个轻量的防抖工具函数,再把你的resizeChild方法包装成防抖版本:
class ResizeComponent extends React.Component { constructor(props) { super(props); this.state = { width: 0 }; // 创建防抖后的resize方法,延迟200ms执行(可根据需求调整时长) this.debouncedResize = this.debounce(this.resizeChild, 200); } // 手写防抖核心逻辑 debounce(func, delay) { let timerId; return (...args) => { // 每次触发鼠标事件时,清除之前未执行的定时器 clearTimeout(timerId); // 重新设置定时器,延迟执行目标函数 timerId = setTimeout(() => { func.apply(this, args); }, delay); }; } resizeChild(e) { // 这里的setState只会在鼠标停止移动200ms后执行一次 this.setState({ width: e.clientX }); } componentWillUnmount() { // 组件卸载时清除定时器,避免内存泄漏 clearTimeout(this.debouncedResize.timerId); } render() { return ( <body onMouseMove={this.debouncedResize}> <div style={{ width: this.state.width, border: '1px solid #333' }}>Resize me</div> </body> ); } }
方案二:使用Lodash的debounce(更省心)
如果你的项目已经引入了Lodash,直接用它封装好的debounce函数更高效:
import { debounce } from 'lodash'; class ResizeComponent extends React.Component { constructor(props) { super(props); this.state = { width: 0 }; // 包装防抖方法,注意绑定组件this指向 this.debouncedResize = debounce(this.resizeChild, 200).bind(this); } resizeChild(e) { this.setState({ width: e.clientX }); } componentWillUnmount() { // 取消所有待执行的防抖调用,避免内存泄漏 this.debouncedResize.cancel(); } render() { return ( <body onMouseMove={this.debouncedResize}> <div style={{ width: this.state.width, border: '1px solid #333' }}>Resize me</div> </body> ); } }
关键注意事项
- 延迟时长调整:建议设为100-300ms,既能保证操作的流畅感,又能有效降低渲染频率。
- 内存泄漏预防:一定要在组件卸载时清除定时器或取消防抖调用,避免无用的回调继续占用资源。
- this指向问题:不管用哪种方案,都要确保
resizeChild里的this指向组件实例,不然setState会报错。
这样改造后,只有当鼠标停止移动超过设定的延迟时间时,才会触发setState和组件渲染,完美解决频繁渲染的问题!
内容的提问来源于stack exchange,提问作者vuvu
相关产品推荐
相关产品推荐

