【React】实现输入框切换

需求

类似designable-antd平台的这个切换功能:

  • 点击右边按钮,可以切换不同的输入框样式。

实现

  • 维护一个type-component的类型数组
  • 遍历数组,找到当前组件类型并渲染
  • 当切换输入框样式的时候,获取下一个组件类型并渲染。如果为最后一个组件,则重新循环为第一个组件类型并展示
  • 初始化的时候,需要根据value校验当前组件的类型,并渲染

polyInput.tsx:

javascript 复制代码
import React, { useEffect, useState, useMemo } from 'react';
import { Button, Row, Tooltip } from 'antd';
import { useField } from '@formily/react';
import { Field } from '@formily/core';

export interface IInput {
  value: any;
  onChange: (value: any) => void;
}

export interface IPolyType {
  type: string;
  icon: JSX.Element;
  component?: any;
  checker: (value: any) => boolean;
}

export type PolyTypes = IPolyType[];

export function createPolyInput(polyTypes: PolyTypes = []): React.FC<IInput> {
  return ({ value, ...props }) => {
    const [curType, setCurType] = useState(polyTypes[0]?.type);

    const field: Field = useField();

    const curTypeItem = polyTypes.filter((i) => i.type === curType)[0];

    useEffect(() => {
      // 设置默认类型
      polyTypes?.forEach(({ checker, type }) => {
        if (checker(value)) { // here
          setCurType(type);
        }
      });
    }, []);

    const getNextType = () => {
      const currentIndex = polyTypes?.findIndex(({ type }) => type === curType);
      const nextIndex = currentIndex + 1 > polyTypes?.length - 1 ? 0 : currentIndex + 1;
      return polyTypes[nextIndex];
    };

    const renderContent = useMemo(() => {
      return (
        <>
          {curTypeItem?.component && (
            <div style={{ flex: 1, marginRight: 5 }}>
              {/* @ts-ignore */}
              {React.createElement(curTypeItem?.component, {
                ...props, // here
                value,
              })}
            </div>
          )}
          <Tooltip title={curTypeItem.type}>
            <Button
              icon={curTypeItem.icon}
              onClick={() => {
                const nextType = getNextType(); // here
                if (nextType.type === curType) {
                  return;
                }
                setCurType(nextType?.type);
                field?.setValue(undefined); // 切换类型的时候,赋空值
              }}
            />
          </Tooltip>
        </>
      );
    }, [curTypeItem]);

    return <Row justify="start">{renderContent}</Row>;
  };
}

使用:

javascript 复制代码
import { FieldStringOutlined, SwitcherOutlined } from '@ant-design/icons';
import { isObject } from 'lodash';
import { Switch } from '@formily/antd';
import LanguageTextRule, { LanguageComponentType } from '../LanguageTextRule';
import { createPolyInput } from '../PolyInput';

export enum ValidatorType {
  BOOLEAN = 'boolean',
  LANGUAGE_MESSAGE = 'message',
}

export const isBoolean = (value: any) => typeof value === 'boolean';
export const isObj = (value: any) => isObject(value);

export const ValidatorTypesMap = [
  {
    type: ValidatorType.BOOLEAN,
    icon: <SwitcherOutlined />,
    component: Switch,
    checker: isBoolean,
  },
  {
    type: ValidatorType.LANGUAGE_MESSAGE,
    icon: <FieldStringOutlined />,
    component: (props: any) => {
      return (
        <LanguageTextRule
          title="Error Message"
          componentType={LanguageComponentType.TEXT}
          buttonText="+ Error Message"
          isModal
          {...props}
        />
      );
    },
    checker: isObj,
  },
];

export default createPolyInput(ValidatorTypesMap);

效果

相关推荐
子午30 分钟前
基于DeepSeek的智能校园教务管理系统~Web管理系统+Vue3+Python+DeepSeek智能问答
前端
change_fate35 分钟前
ERR_PNPM_WORKSPACE_PKG_NOT_FOUND In ...
java·服务器·前端
超人不会飞_Jay42 分钟前
26.6.3Vue笔记
前端·vue.js·笔记
御坂100271 小时前
Vue - @change应用实现下拉框联动功能
前端·javascript·vue.js
小雨下雨的雨1 小时前
基于 Electron 运行时的鸿蒙PC桌面应用-安全可靠的随机密码生成工具
前端·javascript·华为·electron·前端框架·鸿蒙
瘦瘦瘦大人1 小时前
Vue 项目实现关闭/刷新浏览器窗口前的离开确认提示
前端·javascript·vue.js
大家的林语冰1 小时前
尤雨溪官宣:Vite+ 全员加盟 Cloudflare,正式进军全栈开发和 AI 部署云平台!
前端·javascript·vite
独特的螺狮粉1 小时前
金属硬度与熔点对照表APP - 通过鸿蒙PC Electron框架完整技术实现指南
前端·javascript·electron·前端框架·开源·鸿蒙
Java_2017_csdn1 小时前
在 Java 中,MessageFormat.format() 和 String.format() 函数对比?
java·开发语言·前端·数据库
IT策士1 小时前
第 44篇 k8s之实战:将 Web 应用迁移到 Kubernetes(上)
前端·容器·kubernetes