本项目旨在封装多种风格的 React 输入框组件,开发者无需重复编写样式与组件逻辑,只需通过 `npm install` 即可快速引入并使用不同样式的输入框。组件整体设计以简单、可扩展、样式可插拔为核心目标。使用者可以根据项目需求选择不同风格的输入框样式,或在项目中自定义拓展更多样式。

组件库采用 **TypeScript + React** 开发,并支持现代前端构建工具(Vite、Webpack、Next.js 等)无缝集成。

https://github.com/xiyangyanghemeiyangyang/react-input

(主包整整搞了一周才弄成功,因此这篇文章就是一个总结,顺便记录一下项目中遇到的问题和解决方法)

一、明确代码文件结构

首先参考一些github上面的npm react代码,可以发现主要的代码框架基本如下:

react-input/

├─ src/

│  ├─ components/

│  │  └─ InputBase.tsx       //输入框基础逻辑,可复用

│  ├─ page/                   

│  │  ├─ page1/               //样式 1

│  │  │  ├─ index.tsx         // 组件

│  │  │  └─ style.css         //必须:样式配置(如果没有把这个.css单独列出来的话使用这个组件的时候就要在scr目录下面添加./react-input-styles.css,这就很麻烦,违背了这个项目的初衷)

│  │  ├─ page2/               // 样式 2

│  │  │  ├─ index.tsx

│  │  │  └─ style.css

│  │  └─ ... 更多样式

│  └─ index.ts                // 组件库统一导出入口(必要部分,不然没办法导出来)

|     |——style.css                //这个也是要添加上去的,导入买个page文件里面的css样式

├─ package.json               //每次publish代码的时候必须在这个里面做更改,不然publish会失败

├─ README.md

└─ tsconfig.json

这里我刚开始在每个/page里面只写了index.tsx,把样式和逻辑放到了一快,这里卡了很久,不修改react-input的话会很麻烦,不仅要引入Tailwind CSS,创建两个文件,这里我一直创建不出来,最后还是手动创建了两个,还要改package.json里面的一些参数,创建引入./react-input-styles.css,很麻烦,所以还是要改react-input。

二、确定要封装的输入框样式

这里我在谷歌上找到了一些样式,首先要明确他们的逻辑是什么,先写出来一个index.tsx来表示他们的功能逻辑和样式,输入框的最基本逻辑就是判断点击,也就是Focus,比如我这里找到了4种,每一种都包括三个状态:1.正常不聚焦的时候。2.聚焦输入的时候。3.输入错误的时候。

1.点击时显示输入框颜色

Page1.tsx:
export const Page1Input = ({
  status = 'default',
  prefixIcon,//前缀
  suffixIcon,//后缀
  className = '',
  disabled,
  ...props
} : InputProps) => {
  const [isFocused, setIsFocused] = useState(false);

  //框的样式
  const getBorderColor = () => {
    if (disabled) return 'border-gray-200 bg-gray-50';
    if (status === 'error') return 'border-red-500 focus:ring-red-200';
    if (status === 'success') return 'border-green-500 focus:ring-green-200';
    return 'border-gray-300 focus:border-indigo-500 focus:ring-indigo-100';
  };

  const getIconColor = () => {
    if (disabled) return 'text-gray-300';
    if (status === 'error') return 'text-red-500';
    if (status === 'success') return 'text-green-500';
    return isFocused ? 'text-indigo-500' : 'text-gray-400';
  };
    return (
        onFocus={(e) => {
            setIsFocused(true);
            props.onFocus?.(e);
          }}
          onBlur={(e) => {
            setIsFocused(false);
            props.onBlur?.(e);
          }}
    )

2.点击的时候展开,不点击时折叠

Page2.tsx:
export const Page2Input = ({
  status = 'default',//初始状态
  prefixIcon,
  suffixIcon,
  className = '',
  placeholder, 
  value,
  disabled,
  ...props
} : InputProps) => {
  const [isFocused, setIsFocused] = useState(false);
  const hasValue = value != null && String(value).length > 0;


  const getColor = () => {
    if (disabled) return 'text-gray-400 border-gray-200 bg-gray-50';
    if (status === 'error') return 'text-red-600 border-red-500';
    if (status === 'success') return 'text-green-600 border-green-500';
    return isFocused ? 'text-blue-600 border-blue-600' : 'text-gray-500 border-gray-300 hover:border-gray-400';
  };

  const labelActive = isFocused || hasValue;

3.输入框有底色

Page3.tsx:
export const Page3Input = ({
  status = 'default',
  prefixIcon,
  suffixIcon,
  className = '',
  disabled,
  ...props
} : InputProps) => {
  
  const getShadows = () => {
    if (disabled) return 'shadow-none bg-gray-100 border-transparent';
    if (status === 'error') return 'shadow-[inset_2px_2px_4px_#ef444420,inset_-2px_-2px_4px_#ffffff] border-red-200 bg-red-50/10';
    if (status === 'success') return 'shadow-[inset_2px_2px_4px_#22c55e20,inset_-2px_-2px_4px_#ffffff] border-green-200 bg-green-50/10';
    
    return 'shadow-[inset_2px_2px_5px_rgba(163,177,198,0.3),inset_-2px_-2px_5px_rgba(255,255,255,0.8)] bg-[#F0F4F8] border-transparent focus:shadow-[inset_2px_2px_5px_rgba(163,177,198,0.4),inset_-2px_-2px_5px_rgba(255,255,255,0.8),0_0_0_2px_rgba(163,177,198,0.2)]';
  };

4.和1差不多,换个颜色和边框大小

这里的代码其实谷歌上刚开始给的是

export const Page1Input: React.FC<InputProps> = ({
  status = 'default',
  prefixIcon,
  suffixIcon,
  className = '',
  disabled,
  ...props
}) => {
  const [isFocused, setIsFocused] = useState(false);

这里有一个问题,就是: React.FC<InputProps> =这里,最好是改成我上面写的那样,不然在后面会出现props传到出错。

三、根据上面的逻辑提出基础的逻辑

这一步就是完成/component里面的代码,这里可以让AI帮我们提取一下,提示词:请你帮我根据上面我给的四个代码,提取其作为输入框的基础逻辑,放在/component/InputBase.tsx里面,然后剩下的放如/page里面,每个样式单独设立一个/page1的文件,包括其输出index.tsx和其css样式style.css

这里AI出了一个问题,导致我一直在验证项目rreact-input-demo里面一直无法渲染出导入的效果,问题是在每一个/page文件里面的style.css里面的是.ri-page1,但是在index.tsx里面却变成了page1-input所以一直不成功,这里改一下就行了(卡在这一步AI也给我找不出来错,我服了,我心疼我的token...):

四、build和publish

在这个过程中我主要遇到的问题是:

1.每一次改完react-input里面的代码发布的时候,在react-input-demo里面一定要重新下载'react-input-style',不然相当于没有修改!

2.每一次修改的时候要修改package,json里面的version,不然会导致发布失败

五、做一个react-input-demo项目来验证是否成功

就启动一个简单的react-ts项目:npm create vite@latest my-react-app -- --react-input-demo然后把App.tsx换成:

import { Page1Input, Page2Input } from 'react-input-styles';
import 'react-input-styles/styles.css';(must!!!)

export default function Demo() {
  return (
    <>
      <Page1Input placeholder="请输入用户名" />
      <Page2Input status="error" />
    </>
  );
}

浏览器页面出现这样就成功了:

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐