React+TS前台项目实战(六)-- 全局常用组件Button封装

news/2024/6/18 20:46:29 标签: react.js, 前端, typescript, 前端框架

文章目录

  • 前言
  • Button组件
    • 1. 功能分析
    • 2. 代码+注释说明
    • 3. 使用方式
    • 4. 效果展示
    • (1)有加载动画,执行promise函数
    • (2)无加载动画,执行click事件
  • 总结


前言

今天这篇主要讲全局按钮组件封装,可根据UI设计师要求自定义修改。


Button组件

1. 功能分析

(1)可以通过className属性自定义按钮样式,传递样式类名来修改按钮的样式
(2)是否可点击由disabled属性控制,当disabled为true时,按钮被禁用
(3)加载状态由loading属性控制,当loading为true时,按钮显示加载动画
(4)当点击事件回调是Promise函数,执行后续处理;否则直接调用click点击事件

2. 代码+注释说明

// @/components/Button/index.tsx
import { useState } from "react";
import classNames from "classnames";
import styles from "./index.module.scss";

// 组件的属性类型
type Props = {
  // 按钮的文本
  text: string;
  // 自定义的类名
  className?: string;
  // 是否禁用按钮
  disabled?: boolean;
  // 是否显示加载动画
  loading?: boolean;
  // 点击按钮时的回调函数
  click?: () => void;
  beforeChange?: (() => Promise<any>) | undefined;
};

// 按钮组件
export default (props: Props) => {
  // 解构属性
  const { text, className, disabled, loading, beforeChange, click } = props;
  const [load, setLoad] = useState(false);
  /**
   * 点击按钮时的事件处理函数
   * - 如果按钮被禁用,则直接返回
   * - 如果 beforeChange 是一个Promise函数,则调用其后续处理
   * - 否则直接调用 click
   */
  const handleClick = () => {
    if (disabled) return undefined;
    const isFunction = Object.prototype.toString.call(beforeChange) === "[object Function]";
    if (!isFunction) {
      click?.();
      return false;
    }
    // 启用加载动画
    setLoad(true);
    beforeChange?.().finally(() => setLoad(false));
  };
  return (
    // 按钮元素
    <button
      type="button"
      // 设置类名
      className={classNames(
        styles.container,
        // 禁用或加载时增加特定的类名
        (disabled || loading) && styles.isDisabled,
        className
      )}
      // 禁用时禁用快捷键操作
      onKeyDown={handleClick}
      // 禁用时禁用点击事件
      onClick={handleClick}
    >
      {/* 加载动画 */}
      {loading && load && <i className={`${styles.loading} iconfont icon-loading`}></i>}
      {/* 按钮文本 */}
      <span>{text}</span>
    </button>
  );
};
------------------------------------------------------------------------------
// @/components/Button/index.module.scss
.container {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 40px;
  color: #fff;
  background-color: var(--cd-primary-color);
  border-radius: 4px;
  border: none;
  cursor: pointer;
  span {
    font-size: 14px;
    line-height: 14px;
  }
  &:hover {
    background-color: var(--cd-primary-color);
  }
  .isDisabled {
    opacity: 0.5;
    cursor: not-allowed;
  }
  @keyframes rotate {
    0% {
      transform: rotate(0deg);
    }
    50% {
      transform: rotate(180deg);
    }
    100% {
      transform: rotate(360deg);
    }
  }
  .loading {
    font-size: 24px;
    animation: rotate 2s linear infinite;
  }
}

3. 使用方式

// 引入组件
import Button from "@/components/Button";
// 有加载动画使用方式
<Button text="有loading" loading={true} beforeChange={onDoneChange}></Button>
// 点击按钮触发loading
const onDoneChange = () => {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log("onDoneChange");
      resolve(true);
    }, 2000);
  });
};

-----------------------------------------------------------------------------------------------------

// 无加载动画使用方式
<Button text="有loading" loading={false} beforeChange={onDoneClick}></Button>
// 点击按钮不触发loading
const onDoneClick = () => {
  console.log("onDoneClick");
};

4. 效果展示

(1)有加载动画,执行promise函数

在这里插入图片描述
在这里插入图片描述

(2)无加载动画,执行click事件

)


总结

下一篇讲【全局模态框Modal组件、公共弹窗Dialog组件封装】。关注本栏目,将实时更新。


http://www.niftyadmin.cn/n/5520112.html

相关文章

next.js v14 升级全步骤|迁移 pages Router 到 App Router

【概括】本文升级整体按照官网文档指引进行&#xff0c;在迁移 pages Router 前先看了官网的实操视频。 【注意】文章内对 .babel.ts、next.config.js 进行了多次更改&#xff0c;最终配置可见 报错3: Server Error ReferenceError: React is not defined 一、升级 Next.js 版…

pdf.js实现web h5预览pdf文件(兼容低版本浏览器)

注意 使用的是pdf.js 版本为 v2.16.105。因为新版本 兼容性不太好&#xff0c;部分手机预览不了&#xff0c;所以采用v2版本。 相关依赖 "canvas": "^2.11.2", "pdfjs-dist": "^2.16.105", "core-js-pure": "^3.37.…

node 升级之后 npm run build 错误

错误信息 Error Error: error:0308010C:digital envelope routines::unsupportedat new Hash (node:internal/crypto/hash:67:19)at Object.createHash (node:crypto:130:10)该错误源于您对过时的 SSL 版本的依赖&#xff0c;因此您有两个好的选择和两个最好但值得怀疑的选择&…

flutter实现UDP发送魔法包唤醒主机

魔法包 魔法包是用16进制表示的数据包&#xff0c;它是由固定的前缀数据(FFFFFFFFFFFF)以及固定重复次数(16次)的目标主机MAC地址组成。 假设目标主机的MAC地址是&#xff1a;"50:eb:f6:27:ae:a8" 那么魔法包就是[FFFFFFFFFFFF50EBF627AEA850EBF627AEA850EBF627AEA8…

表的删除与更新

表的删除与更新 表的删除 DROP 删除表 执行此操作一定要慎重&#xff01;&#xff01;&#xff01;&#xff01;因为表在删除后想要恢复是费时费力的工作&#xff0c;可以说是很难很难。 删除表的语法为&#xff1a; DROP TABLE 数据表名;示例&#xff1a; DROP TABLE st…

【Oracle生产运维】数据库服务器高负载排查处理

说明 在Oracle数据库运维工作中&#xff0c;经常会遇到Oracle数据库服务器平均负载&#xff08;load average&#xff09;突然异常升高&#xff0c;如果放任不管&#xff0c;严重的情况下会出现数据库宕机、服务器重启等重大故障。因此&#xff0c;当发现数据库服务器平均负载…

CSS 提示工具:增强网站互动性与用户体验

CSS 提示工具&#xff1a;增强网站互动性与用户体验 在网页设计中&#xff0c;CSS&#xff08;层叠样式表&#xff09;不仅用于美化网站&#xff0c;还能增强网站的互动性和用户体验。CSS 提示工具&#xff08;Tooltips&#xff09;是一种常见的交互元素&#xff0c;它能在用户…

05.VisionMaster 机器视觉 结果 格式化输出

VisionMaster 机器视觉 结果 格式化输出 格式化工具可以把数据整合并格式化成字符串输出&#xff0c;它既可以链接前面模块的结果输出&#xff0c;也可以直接在框内输入字符格&#xff0c;在进行通信输出前通常用格式化工具将数据进行整理&#xff0c; 如下图所示。 前面的文章…