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



    前言

    今天这篇主要讲全局按钮组件封装,可根据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组件封装】。关注本栏目,将实时更新。

  • 相关阅读:
    李书福为何要亲自挂帅造手机?
    c# 多线程处理
    传奇开服教程——legend/blue引擎替换和登陆器生成教程
    数据结构与算法训练:第二十六章
    初识Linux:目录的创建&销毁
    Kafka内容相关
    c++ 广度优先搜索(Breadth-First Search,BFS)
    动态规划例题--python和java题解
    laravel如何通过DB获取一条数据并转成数组
    多模态相关论文笔记
  • 原文地址:https://blog.csdn.net/weixin_43883615/article/details/139594504