You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:50:10