react组件开源-计数器

89 阅读1分钟

定义变量

export interface InputNumberProps {
  /**
   * @description 初始值
   * @default 1
   */
  value?: number;
  /**
   * @description 最小值
   * @default 0
   */
  min?: any;
  /**
   * @description 最大值
   * @default 99999999
   */
  max?: any;
  /**
   * @description 宽度
   * @default 150px
   */
  width?: any;
  /**
   * @description 高度
   * @default 45px
   */
  height?: any;
  /**
   * @description 是否禁用
   * @default false
   */
  disabled?: boolean;
  /**
   * @description 自定义cahnge事件
   */
  change?: Function;
  /**
   * @description 自定义失去焦点事件
   */
  blur?: Function;
  /**
   * @description 自定义焦点事件
   */
  focus?: Function;
  /**
   * @description 按钮位置
   * @default center
   */
  controlsPosition?: 'left' | 'rigth' | 'center';
}

主要实现方式

import React, { useState, FC, memo } from 'react';
import Css from './index.module.less';
import { InputNumberProps } from './interface';

const InputNumber: FC<InputNumberProps> = memo(
  ({ value, min, max, width, height, disabled, change, blur, focus, controlsPosition }) => {
    let [num, setNum] = useState(value ? value : 0);
    let [active, setActive] = useState(false);

    let style = {
      width: '150px',
      height: '45px',
    };

    let position = '';

    if (!max) {
      max = 99999999;
    }

    if (!min) {
      min = 0;
    }

    if (controlsPosition === 'left') {
      position = 'left';
    } else if (controlsPosition === 'rigth') {
      position = 'rigth';
    }

    if (width) {
      if (typeof width === 'string') {
        if (width.includes('%') || width.includes('px')) {
          style.width = width;
        }
      } else if (width * 1) {
        style.width = width + 'px';
      }
    }

    if (height) {
      if (typeof height === 'string') {
        if (height.includes('%') || height.includes('px')) {
          style.height = height;
        }
      } else if (height * 1) {
        style.height = height + 'px';
      }
    }

    const minus = () => {
      if (num <= min) {
        setNum(min);
      } else if (!disabled) {
        setNum(num - 1);
      }
      return change ? change({ value: num }) : null;
    };

    const add = () => {
      if (num >= max) {
        setNum(max);
      } else if (!disabled) {
        setNum(num + 1);
      }
      return change ? change({ value: num }) : null;
    };

    const handleFocus = () => {
      setActive(true);
      return focus ? focus({ value: num }) : null;
    };

    const handleBlur = () => {
      setActive(false);
      return blur ? blur({ value: num }) : null;
    };

    let className = [
      Css['input_number'],
      disabled ? Css['disabled'] : '',
      !disabled ? Css['defaule'] : '',
      position ? Css[position] : '',
      active ? Css['active'] : '',
    ].join(' ');

    return (
      <div className={className} style={style}>
        <span
          className={Css.minus}
          onClick={() => {
            minus();
          }}
        ></span>
        <input
          className={Css.input}
          disabled={disabled}
          type="text"
          min={min}
          max={max}
          value={num}
          onBlur={() => {
            handleBlur();
          }}
          onFocus={() => {
            handleFocus();
          }}
        />
        <span
          className={Css.add}
          onClick={() => {
            add();
          }}
        ></span>
      </div>
    );
  },
);
export default InputNumber;

主要思路

用响应数据存储变量,并添加向左向右的点击事件,来修改响应式数据的值