·
Across the Great Wall, we can reach every corner in the world.

黑客说是用 js 实现的,给你一个完整的 Tab 组件代码:

import React, {
  FC,
  MouseEvent,
  ReactElement,
  ReactNode,
  Children,
  isValidElement,
  useState,
  useEffect
} from 'react';
import { Link } from 'react-router-dom';
import clsx from 'clsx';

interface TabProps {
  type?: 'link' | 'button';
  label?: string;
  value?: string | number;
  replace?: boolean;
  disabled?: boolean;
  children?: ReactNode;
}

interface TabsProps {
  defaultValue?: string | number;
  children: ReactElement<TabProps> | (ReactElement<TabProps> | ReactNode)[];
  onChange?: (value: string | number) => void;
}

export const Tab: FC<TabProps> = ({ children }) => {
  return <div>{children}</div>;
};

Tab.defaultProps = {
  type: 'button',
  replace: true,
};

const Tabs: FC<TabsProps> = ({ children, defaultValue, onChange }) => {
  const [value, setValue] = useState<string | number>(defaultValue || '');

  useEffect(() => {
    setValue(defaultValue || '');
  }, [defaultValue]);

  const onClickTab = (newValue?: string | number) => (e: MouseEvent) => {
    e.stopPropagation();
    setValue(newValue || '');
    onChange?.(newValue || '');
  };

  return (
    <div className="bg-content border-main-content">
      <div className="h-13 px-4 flex items-center space-x-2">
        {Children.map(children, element => {
          if (!isValidElement<TabProps>(element)) {
            return null;
          }
          const className = clsx(
            'text-sm font-bold px-3 py-1.5 rounded-lg',
            value === element.props.value
              ? 'text-blue-500 bg-slate-100 dark:bg-slate-700'
              : 'text-color-secondary bg-btn'
          );
          if (element.props.type === 'link') {
            return (
              <Link
                className={className}
                to={element.props.value ? `${element.props.value}` : '/'}
                replace={element.props.replace}
              >
                {element.props.label}
              </Link>
            );
          }

          return (
            <button
              disabled={element.props.disabled}
              className={className}
              onClick={onClickTab(element.props.value)}
            >
              {element.props.label}
            </button>
          );
        })}
      </div>
      <div className="mx-4 border-t-primary" />
      {Children.map(children, element => {
        if (!isValidElement<TabProps>(element)) return null;
        if (element.props.value !== value) return null;
        return element;
      })}
    </div>
  );
};

export default Tabs;