React+TS前台项目实战(十九)-- 全局常用组件封装:带加载状态和清除等功能的Input组件实现


前言

今天我们来封装一个input输入框组件,并提供一些常用的功能,你可以选择不同的 尺寸添加前缀显示加载状态触发回调函数自定义样式 等等。这些功能在这个项目中已经足够了,无论你是一个经验丰富的开发者还是一个刚刚入门的新手,这篇文章都将提供有用的知识和实践经验,以帮助你在自己项目中封装输入框时更加高效


Input组件

1. 功能分析

(1)通过传入loading加载状态属性,当激活时会显示加载图标
(2)通过传入size属性, 可以有不同的大小:“default”、“small” 或 “large”
(3)提供onChange值发生变化回调函数;失去焦点onBlur回调函数;键盘回车onKeyUp回调函数;
(4)当输入框有值时,组件会显示一个清除按钮,用户可以通过点击按钮来清除输入框的值
(5)通过传入className属性, 可以自定义输入框的样式
(6)通过 elprops 属性将其他属性传递给底层的 input 元素

2. 代码+详细注释

// @/components/Input/index.tsx
import { FC, ReactNode, useCallback, useState, ChangeEventHandler, FocusEvent, ComponentPropsWithoutRef, KeyboardEventHandler } from "react";
import classNames from "classnames";
import { InputContainer } from "./styled";
import { ReactComponent as SearchIcon } from "./assets/search.svg";
import { ReactComponent as LoadingIcon } from "./assets/loading.svg";
import { ReactComponent as ClearIcon } from "./assets/clear.svg";
import SimpleButton from "@/components/SimpleButton";

// 组件的属性类型
type Props = Omit<ComponentPropsWithoutRef<"input">, "size"> & {
  // 按下回车的回调
  onEnter?: () => void;
  // 是否显示加载状态
  loading?: boolean;
  // 输入框大小
  size?: "default" | "small" | "large" | undefined;
  // 输入框前缀
  prefix?: boolean | ReactNode;
};

// 输入框组件
const Input: FC<Props> = ({ loading, size, onEnter, value: propsValue, onChange: propsOnChange, onKeyUp: propsOnKeyUp, onBlur: propsOnBlur, className, ...elprops }) => {
  // 输入框的值,通过状态管理
  const [value, setValue] = useState(propsValue);

  // 输入事件
  const handlerChange: ChangeEventHandler<HTMLInputElement> = useCallback(
    (event) => {
      // 如果正在加载,直接返回
      if (loading) {
        return;
      }
      // 更新状态和回调
      setValue(event.target.value);
      propsOnChange?.(event);
    },
    [propsOnChange, setValue, loading]
  );

  // 回车事件
  const onKeyUp: KeyboardEventHandler<HTMLInputElement> = useCallback(
    (event) => {
      // 如果是回车键,触发回调
      const isEnter = event.keyCode === 13;
      if (isEnter) {
        onEnter?.();
      }
      propsOnKeyUp?.(event);
    },
    [onEnter, propsOnKeyUp]
  );

  // 失去焦点事件
  const onBlur = useCallback(
    (event: FocusEvent<HTMLInputElement>) => {
      propsOnBlur?.(event);
    },
    [propsOnBlur]
  );

  return (
    <InputContainer className={classNames(className)} size={size}>
      {/* 加载状态图标 */}
      {loading ? <LoadingIcon className={classNames("input-loading-icon")} /> : <SearchIcon className={classNames("input-search-icon")} />}
      {/* 输入框 */}
      <input enterKeyHint="search" value={value} onChange={handlerChange} onKeyUp={onKeyUp} onBlur={onBlur} {...elprops} />
      {/* 清除按钮 */}
      {value && (
        <SimpleButton className={classNames("input-clear-icon")} title="clear" onClick={() => setValue("")}>
          <ClearIcon />
        </SimpleButton>
      )}
    </InputContainer>
  );
};

export default Input;
------------------------------------------------------------------------------
// @/components/Input/styled.tsx
import styled from "styled-components";
import variables from "@/styles/variables.module.scss";
type InputProps = {
  size: "default" | "small" | "large" | undefined;
};
export const InputContainer = styled.div<InputProps>`
  @keyframes rotate {
    100% {
      transform: rotate(360deg);
    }
  }
  position: relative;
  margin: 0 auto;
  width: 100%;
  height: ${({ size }) => {
    if (size === "default") return "var(--cd-input-height)";
    else if (size === "small") return "var(--cd-input-sm-height)";
    else return "var(--cd-input-large-height)";
  }};
  padding-right: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: white;
  border: 0 solid white;
  border-radius: 4px;
  input {
    position: relative;
    width: 100%;
    height: 100%;
    font-size: 14px;
    padding: 0 8px;
    background: #fff;
    color: #333;
    border: 0 solid #fff;
    border-radius: 5px;
    &:focus {
      color: #333;
      outline: none;
    }
    &::placeholder {
      color: #888;
    }
    @media (max-width: ${variables.mobileBreakPoint}) {
      font-size: 12px;
      width: 100%;
      padding-left: 6px;
      padding-right: 16px;
    }
  }
  .input-loading-icon,
  .input-search-icon {
    flex-shrink: 0;
    width: 20px;
    height: 20px;
    margin-left: 8px;
  }
  .input-loading-icon {
    animation: rotate 2s linear infinite;
  }
  .input-clear-icon {
    display: flex;
    align-items: center;
    flex-shrink: 0;
  }
`;

3. 使用方式

// 引入组件
import Input from '@/components/Input'
// 使用
const [loading, setLoading] = useState(false);
const [searchkeyword, setSearchkeyword] = useState("");
{/* 输入框值变化回调事件 */}
const onInputChange: ChangeEventHandler<HTMLInputElement> = (event) => {
  console.log("onInputChange", event.target.value);
  setSearchkeyword(event.target.value);
};
{/* 失焦回调事件 */}
const onInputBlur = () => {};
{/* 小尺寸,不带loading */}
<Input placeholder="请输入" size="small" />
{/* 标准尺寸,带loading */}
<Input placeholder="请输入" loading={loading} onChange={onInputChange} onBlur={onInputBlur} />
{/* 大尺寸,不带loading */}
<Input placeholder="请输入" size="large" />
{/* 带前缀 */}
<Input hasPrefix placeholder="请输入" loading={loading}} />
{/* 不带前缀 */}
<Input placeholder="请输入" loading={loading} onChange={onInputChange} onBlur={onInputBlur} />

4. 效果展示

(1)输入后,加载效果如下
注:如请求数据时添加加载状态,请求结束后取消加载状态

在这里插入图片描述

(2)点击清除按钮,清除数据效果

在这里插入图片描述

(3)三种尺寸显示如下

在这里插入图片描述
(4)带前缀 / 不带前缀效果
在这里插入图片描述


总结

下一篇讲【全局常用Search组件封装】。关注本栏目,将实时更新。

  • 12
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
作为前端使用ReactTypeScriptReact Router、Redux、Axios、Ant Design和Sass开发ERP软件项目的职责描述,主要包括以下几个方面: 1. 分析需求和设计界面:与产品经理、设计师等团队成员合作,分析用户需求和产品设计,设计符合用户需求的界面,并提供良好的用户体验。 2. 使用ReactTypeScript开发组件:根据设计稿或需求文档,使用ReactTypeScript开发可复用的组件,利用类型检查提高代码的可靠性和可维护性。 3. 使用React Router实现路由管理:使用React Router进行页面之间的导航和路由管理,确保页面之间的跳转和参数传递的正常。 4. 使用Redux进行状态管理:使用Redux进行全局状态的管理,包括定义和处理数据流、异步操作、状态持久化等,确保数据的一致性和可控性。 5. 使用Axios进行网络请求:使用Axios库发送HTTP请求与后端API进行数据交互,并处理请求的错误和异常情况。 6. 使用Ant Design进行UI开发:使用Ant Design提供的组件库进行界面开发,保证界面的一致性和美观性,并根据需求进行自定义样式。 7. 使用Sass进行样式管理:使用Sass预处理器编写可复用的样式代码,提高样式开发效率,并保持样式的可维护性。 8. 优化性能和用户体验:通过前端优化技术(如代码分割、懒加载、缓存等),提升ERP软件的性能和用户体验,确保页面加载速度快、操作流畅。 9. 跨浏览器兼容性测试:测试并确保ERP软件在各种主流浏览器(如Chrome、Firefox、Safari等)下的正常运行,并解决兼容性问题。 10. 代码版本管理和团队协作:使用版本管理工具(如Git)管理代码,与团队成员协作开发,参与代码评审和项目迭代。 11. 系统维护和故障排除:及时响应用户反馈并解决软件中出现的前端问题,修复bug,确保ERP软件的稳定运行。 总的来说,前端使用ReactTypeScriptReact Router、Redux、Axios、Ant Design和Sass开发ERP软件项目的职责是负责开发和维护ERP软件的前端界面和功能,与后端进行数据交互,优化性能和用户体验,并与团队成员协作推动项目的成功交付。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值