封装一个输入框样式(npm react)
本项目旨在封装多种风格的 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" />
</>
);
}
浏览器页面出现这样就成功了:
更多推荐
所有评论(0)