DebounceClick 组件

发布于 2023-07-29 10:47:08 字数 2542 浏览 32 评论 0

在日常开发中会有这样的需求,对点击事件进行防抖处理,比如点击按钮会进行请求,那假如多次点击则不希望每次都触发请求,对后端接口不利。通常的做法是,每次在 constructor 中将点击事件处理函数变为防抖函数:

constructor(props){
  ...
  this.handleClick = this.handleClick.bind(this)
  this.handleClick = _.debounce(this.handleClick, debounceMillis)
}

render(){
  <div onClick={this.handleClick}>
  ...
  </div>
}

这样不好的是每次需要防抖都要写一遍重复的代码,因此基于高阶组件的思路,来写一个点击防抖组件:

import React, { Component } from 'react';
import debounce from 'lodash.debounce';
import PropTypes from 'prop-types';

class DebounceClick extends Component {
  constructor(props) {
    super(props);
    const { children, debounceMillis, persist } = props;
    const { onClick } = children.props;
    const debounceHandle = debounce(onClick, debounceMillis);
    if (persist) {
      // in debounce source code, there is async code `setTimeout`
      // so if we want to call e.persist(), we can only do here, or change debounce source code
      this.handle = e => {
        e.persist();
        debounceHandle(e);
      };
    } else {
      this.handle = debounceHandle;
    }
  }

  noop() {}

  render() {
    const { children, active } = this.props;
    return React.cloneElement(children, { onClick: active ? this.handle : this.noop });
  }
}

DebounceClick.propTypes = {
  debounceMillis: PropTypes.number,
  persist: PropTypes.bool,
  active: PropTypes.bool,
};

DebounceClick.defaultProps = {
  debounceMillis: 500, // 500 is better, 200ms for most user, this will appear almost instantly
  persist: false,
  active: true, // false means not trigger onClick
};

export default DebounceClick;

为了让该高阶组件尽量不与需要防抖的组件耦合,因此 onClick 直接从 children.props 中获取。

另外需要注意的是,React 事件采用事件池的方式,意味着事件对象上的一些属性会在事件处理完之后 nullify , 而 debounce 内部由于存在 setTimtout, 导致最终的处理函数 handleClick 即使使用 e.persist() 也不能保留该事件对象。

因此要么改动 debounce 源码,不过改高阶组件一样可以实现:

if (persist) {
  // in debounce source code, there is async code `setTimeout`
  // so if we want to call e.persist(), we can only do here, or change debounce source code
  this.handle = e => {
    e.persist();
    debounceHandle(e);
  };
} else {
  this.handle = debounceHandle;
}

另外有时候不仅是需要防抖,而且能够控制是否触发点击处理函数,因此还接受 active 参数。

调用示例:

<DebounceClick>
  <div onClick={this.handleClick}>
  ...
  </div>
</DebounceClick>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

伴梦长久

暂无简介

文章
评论
27 人气
更多

推荐作者

櫻之舞

文章 0 评论 0

弥枳

文章 0 评论 0

m2429

文章 0 评论 0

野却迷人

文章 0 评论 0

我怀念的。

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文