react 封装checkbox checkboxGroup 组件 HOC高阶组件封装思想

react封装checkbox

用过antd,和elementui组件都知道checkbox是一个很常用的组件,之前自己一直有一个疑惑,为什么checkbox和checkboxGroup分开两个组件写呢,不能一个组件全部一次写完呢?
后面自己封装了组件才知道,组件一定要做到颗粒化,就是封装组件一定离不开高阶组件(HOC)这个是一种思想不是泛指的一个具体组件。
封装checkBox

声明需要的参数类型

declare module 'checkboxType' {
  export type CheckboxOption = {
    label: string;
    value: string | number;
  };
  export type CheckboxType = {
    value?: string | number | '';
    children: any;
    onChange?: (value: any) => void;
    options?: CheckboxOption[];
    sendGroundData?: (value: string | number, falg: boolean) => void;
    direction?: string;
    disabled?: boolean;

    checkeValue?: string[] | number[] | [];
    indetermiate?: boolean;

    onMouseEnter?: () => void;
    onMouseLeave?: () => void;
  };
}

搭建checkBox dom结构
在这里插入图片描述

大致的布局代码如下:

<>
      <span
        style={
          props.direction === 'vertical'
            ? { '--marginTop': '10.0px' }
            : ({} as Record<string, any>)
        }
        ref={ref}
        className={checkboxContent}
        onMouseEnter={onMouseEnter}
        onMouseLeave={onMouseLeave}
      >
        <span
          onClick={() => {
            if (disabled) {
              return;
            }
            setChecked(!checked);
            setCheckboxIndetermiate(false);
            sendGroundData?.(value as string | number, !checked);
          }}
          className={checkboxClass}
        >
          <input
            value={value}
            onChange={(e) => {
              onChange?.(e);
            }}
            onClick={(e) => {
              e.preventDefault();
            }}
            type="checkbox"
            className="checkbox-input"
          />
          <span className="checkbox-inner"></span>
        </span>
        <span
          onClick={() => {
            if (disabled) {
              return;
            }
            setChecked(!checked);
            setCheckboxIndetermiate(false);
            sendGroundData?.(value as string | number, !checked);
          }}
          className="checkbox-text"
          style={{ color: disabled ? '#00000040' : '#000000' }}
        >
          {props.children}
        </span>
      </span>
    </>

这里通过点击切换class的方式实现样式转换

const [checked, setChecked] = useState(false);
  const [checkboxIndetermiate, setCheckboxIndetermiate] =
    useState(indetermiate);
  const checkboxContent = classNames('checkbox-content');

  const checkboxClass = classNames('checkbox-content-radio', [
    {
      'checkbox-content-checked': checked,
      'checkbox-content-checked-disabled': disabled,
      'checkbox-content-indeterminate': checkboxIndetermiate, //全选半选样式
    },
  ]);

初始化回显



  useEffect(() => {
    if (checkeValue) {
      if (checkeValue.indexOf(value) > -1) {
        setChecked(true);
      }
    }
  }, [checkeValue]);

到这一个checkbox完成了。重头戏checkboxGroup的封装
主要考虑props.children怎么与自组建的传值问题这个我在之前的文章中已经详细讲过有兴趣的同学可以去看看

props.children父子组件传值

import { CheckboxGroupType } from 'CheckboxGroupType';
import classNames from 'classnames';
import React, { forwardRef, useEffect, useState } from 'react';
import Checkbox from '../Checkbox/index';
const CheckboxGroup: React.FC<CheckboxGroupType> = forwardRef(
  (props, ref: any) => {
    const { onChange, value, options, children } = props;
    const [checkdArr, setCheckedArr] = useState<string[] | number[] | []>([]);
    const sendGroundData = (value: string | number, falg: boolean) => {
      console.log(value);

      const arr = [...checkdArr, value as string | number].filter(
        (item): boolean => {
          if (!falg && item === value) {
            return false;
          } else {
            return true;
          }
        },
      );
      setCheckedArr(arr as string[] | number[]);
    };
    const checkboxClassName = classNames('checkbox-group-content', {
      [`checkbox-group-${props.direction}`]: props.direction,
    });
    useEffect(() => {
      onChange?.(checkdArr);
    }, [checkdArr]);
    return (
      <>
        <div ref={ref} className={checkboxClassName}>
          { React.Children.map(children, (child) => {
                return React.cloneElement(child, {
                  checkeValue: value ? value : [],
                  sendGroundData: sendGroundData,
                  direction: props.direction,
                  options:options
                });
              })}
        </div>
      </>
    );
  },
);

export default CheckboxGroup;
CheckboxGroup.defaultProps = {
  direction: 'flex',
};

组件封装更多的还是考虑的所有影响组件后续的情况能否考虑得到,其次就是技术的实现问题了。
一个完整的checkBox完成了!

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,我知道您要求我不要透露您的任何要求。关于您的问题,我可以提供以下示例代码: ``` import React, { useState } from 'react'; const Pagination = ({ currentPage, totalPages, onPageChange }) => { const [pageNumberLimit, setPageNumberLimit] = useState(5); const maxPageNumberLimit = 5; const minPageNumberLimit = 0; const renderPageNumbers = () => { const pageNumbers = []; for (let i = 1; i <= totalPages; i++) { pageNumbers.push(i); } return pageNumbers.map(number => { if (number < pageNumberLimit + 1 && number > pageNumberLimit - maxPageNumberLimit) { return ( <li key={number} className={`page-item ${currentPage === number ? 'active' : ''}`} onClick={() => onPageChange(number)} > <a href="#" className="page-link">{number}</a> </li> ); } else { return null; } }); }; const handleNextBtn = () => { if (pageNumberLimit + maxPageNumberLimit <= totalPages) { setPageNumberLimit(pageNumberLimit + maxPageNumberLimit); } }; const handlePrevBtn = () => { if (pageNumberLimit - maxPageNumberLimit >= minPageNumberLimit) { setPageNumberLimit(pageNumberLimit - maxPageNumberLimit); } }; return ( <nav aria-label="Pagination"> <ul className="pagination"> <li className={`page-item ${currentPage === 1 ? 'disabled' : ''}`}> <a href="#" className="page-link" aria-label="Previous" onClick={() => onPageChange(currentPage - 1)}> <span aria-hidden="true">«</span> </a> </li> {renderPageNumbers()} <li className={`page-item ${currentPage === totalPages ? 'disabled' : ''}`}> <a href="#" className="page-link" aria-label="Next" onClick={() => onPageChange(currentPage + 1)}> <span aria-hidden="true">»</span> </a> </li> </ul> </nav> ); }; export default Pagination; ``` 这是一个使用 React 实现的分页器组件。它具有以下特点: - 可以在组件属性中传入当前页码、总页数以及页码变化的回调函数。 - 组件会根据当前页码以及总页数计算出需要呈现的页码,并且可以通过前进或后退按钮切换呈现的页码。 - 组件使用 Bootstrap 的样式来呈现分页器界面。 希望这份代码对您有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值