简体   繁体   English

如何使用 lodash 用 1 个油门来控制多个按钮?

[英]How to use lodash to throttle multiple buttons with 1 throttle?

I'd like to avoid concurrence and restrict the action by 1 per second.我想避免并发并将动作限制为每秒 1 次。

This is because the onChange event also trigger a slide show of 1s duration, and triggering twice is corrupting the UI.这是因为onChange事件还会触发持续时间为 1 秒的幻灯片放映,并且触发两次会破坏 UI。

I initially started with 4 debounces function, but finally got to this:我最初从 4 个去抖功能开始,但最终做到了:

import React from 'react';
import { css } from 'styled-components';
import PropTypes from 'prop-types';
import omit from 'lodash.omit';
import throttle from 'lodash.throttle';
import Img from '@bootstrap-styled/v4/lib/Img';

export default class ServicesAndSolutionImg extends React.PureComponent {
  static propTypes = {
    src: PropTypes.string.isRequired,
    alt: PropTypes.string.isRequired,
    onDigitalSolution: PropTypes.func.isRequired,
    onServices: PropTypes.func.isRequired,
    onHosting: PropTypes.func.isRequired,
    onAddons: PropTypes.func.isRequired,
  };

  state = {
    throttleFn: null,
  }

  componentWillMount() {
    this.setState({
      throttleFn: (e) => throttle(this.props[e.target.value], 1000, { leading: false, trailing: true })(),
    });
  }

  render() {
    const { src, alt } = omit(this.props, [
      'onDigitalSolution',
      'onServices',
      'onHosting',
      'onAddons',
    ]);

    return (
      <div css={css`position: relative`}>
        <Img fluid src={src} alt={alt} className="w-100 pt-3 pl-5 pr-5" />
        <div css={css`
          position: absolute;
          top: 0;
          right: 0;
          left: 0;
          right: 0;
          width: 100%;
          height: 100%;
        `}>
          <div css={css`
            position: relative;
            width: inherit;
            height: inherit;
            button {
              cursor: pointer;
              position: absolute;
              top: 23%;
              height: 51%;
              opacity: 0;
            }
            button:nth-child(1) {
              left: 15%;
              width: 16%;
            }
            button:nth-child(2) {
              left: 32%;
              width: 16%;
            }
            button:nth-child(3) {
              left: 48%;
              width: 16%;
            }
            button:nth-child(4) {
              left: 65%;
              width: 16%;
            }
          `}>
            <button onClick={this.state.throttleFn} value="onDigitalSolution" />
            <button onClick={this.state.throttleFn} value="onServices" />
            <button onClick={this.state.throttleFn} value="onHosting" />
            <button onClick={this.state.throttleFn} value="onAddons" />
          </div>
        </div>
      </div>
    );
  }
}

Expected预期的

No delay, 1 click per second, no concurrency无延迟,每秒1次点击,无并发

Result结果

1 second delay, up to 4 concurrent actions. 1 秒延迟,最多 4 个并发操作。

Does anybody know why this fails?有人知道为什么会失败吗?

Throttle is a function that takes a function, and returns a throttled function. Throttle是一个接受函数并返回节流函数的函数。 The throttled function only invokes the original function once in a window of x milliseconds.节流函数仅在x毫秒的窗口中调用一次原始函数。

Calling throttle multiple times, returns multiple throttled functions, which you invoke, and each of them is the only call in the window of time.多次调用 throttle,返回多个你调用的 throttled 函数,并且它们中的每一个都是时间窗口中的唯一调用。

To fix that, assign the result of calling throttle on the callback to a property on the component, and call that function when you register the click events.要解决此问题,请将回调中调用 throttle 的结果分配给组件上的属性,并在注册点击事件时调用该函数。

export default class ServicesAndSolutionImg extends React.PureComponent {
  static propTypes = {
    src: PropTypes.string.isRequired,
    alt: PropTypes.string.isRequired,
    onDigitalSolution: PropTypes.func.isRequired,
    onServices: PropTypes.func.isRequired,
    onHosting: PropTypes.func.isRequired,
    onAddons: PropTypes.func.isRequired,
  };

  // create the throttled function
  throttleFn = throttle((e) => this.props[e.target.value], 1000, { leading: false, trailing: true })

  render() {
     // no need to omit anything - you know what you want
    const { src, alt } = this.props;

    return (
      <div css={css`position: relative`}>
        <Img fluid src={src} alt={alt} className="w-100 pt-3 pl-5 pr-5" />
        <div css={css`
          position: absolute;
          top: 0;
          right: 0;
          left: 0;
          right: 0;
          width: 100%;
          height: 100%;
        `}>
          <div css={css`
            position: relative;
            width: inherit;
            height: inherit;
            button {
              cursor: pointer;
              position: absolute;
              top: 23%;
              height: 51%;
              opacity: 0;
            }
            button:nth-child(1) {
              left: 15%;
              width: 16%;
            }
            button:nth-child(2) {
              left: 32%;
              width: 16%;
            }
            button:nth-child(3) {
              left: 48%;
              width: 16%;
            }
            button:nth-child(4) {
              left: 65%;
              width: 16%;
            }
          `}>
            <button onClick={this.throttleFn} value="onDigitalSolution" />
            <button onClick={this.throttleFn} value="onServices" />
            <button onClick={this.throttleFn} value="onHosting" />
            <button onClick={this.throttleFn} value="onAddons" />
          </div>
        </div>
      </div>
    );
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM