React+TS前台项目实战(二十三)-- 基于属性自定义数值显示组件Decimal封装

文章目录

  • 前言
  • Decimal组件
    • [1. 功能分析](#1. 功能分析)
    • [2. 代码+详细注释](#2. 代码+详细注释)
    • [3. 使用方式](#3. 使用方式)
    • [4. 效果展示](#4. 效果展示)
  • 总结

前言

今天要封装的Decimal 组件,是通过传入的属性进行定制化显示数值,在渲染时,会根据不同的情况显示整数部分、小数部分和单位,支持自定义样式、布局和单位,同时根据数值正负情况显示不同样式,适用于准确展示各种类型的数值数据。

Decimal组件

1. 功能分析

(1)支持不同的样式(type显示类型,layout布局类型)

(2)支持是否显示小数点后全部小数部分或默认8位小数(display属性)

(3)支持显示不同的单位(unit属性)

(4)结合type属性,判断是否根据数值的正负情况显示不同的样式

(5)使用useMemo,避免重复计算,并且使用 BigNumber 来进行精确的数值计算操作

(6)支持传入 className 自定义类名来修改样式

2. 代码+详细注释

c 复制代码
// @/components/Decimal/index.tsx
import { useMemo, FC } from "react";
import BigNumber from "bignumber.js";
import classNames from "classnames";
import { DecimalContainer } from "./styled";

// 组件的属性类型
type Props = {
  value: string; // 要显示的数值
  type?: "value" | "compare"; // 显示类型,默认为 "value",当需要显示正负值,并且有颜色区分时,使用compare
  layout?: "responsive" | "fixed"; // 布局类型,默认为 "fixed",响应式为responsive
  unit?: "CKB" | string | null; // 显示的单位,默认为 "CKB"
  display?: "full" | "short"; // 显示样式,默认为 "short",显示小数点后8位,为full时显示全部小数部分
  className?: string; // 自定义的类名
};

const Decimal: FC<Props> = (props) => {
  // 解构属性
  const { value, type = "value", layout = "fixed", unit = "CKB", display = "short", className } = props;
  // 使用 useMemo 缓存计算结果,避免重复计算
  const [int, dec, status] = useMemo(() => {
    const c = new BigNumber(value);
    // 将数值格式化为字符串,并分割成整数部分和小数部分
    const [int, dec] = c.toFormat(display === "short" ? 8 : undefined).split(".");
    // 如果是比较模式,并且数值不为零,则返回整数部分和小数部分以及数值的正负
    if (type !== "compare" || c.isZero()) return [int, dec];
    if (c.isPositive()) return [int, dec, "positive"];
    return [int, dec, "negative"];
  }, [value, display, type]);

  return (
    <DecimalContainer className={classNames(className)} data-type={type} data-value-status={status} data-layout={layout}>
      <span className={classNames("int")}>{int}</span>
      {dec && <span className={classNames("dec monospace")}>{`.${dec}`}</span>}
      {unit && <span className={`unit monospace`}>{unit}</span>}
    </DecimalContainer>
  );
};

export default Decimal;
------------------------------------------------------------------------------
// @/components/Decimal/styled.tsx
import styled from "styled-components";
import variables from "@/styles/variables.module.scss";
export const DecimalContainer = styled.div`
  display: inline-flex;
  align-items: flex-end;
  font-size: 16px;
  white-space: nowrap;
  span.dec {
    font-size: 12px;
  }
  .unit {
    margin-left: 5px;
  }
  &[data-type="value"] {
    span.dec {
      color: var(--cd-gray-light-3);
    }
  }
  &[data-type="compare"] {
    color: var(--cd-gray-light-3);
    &[data-value-status="positive"] {
      color: var(--cd-primary-color);
      &::before {
        content: "+";
      }
    }
    &[data-value-status="negative"] {
      color: var(--cd-danger-color);
    }
  }

  &[data-layout="responsive"] {
    @media (max-width: ${variables.mobileBreakPoint}) {
      font-size: 12px;
      span.dec {
        font-size: 10px;
      }
      .unit {
        font-size: 12px;
      }
    }
  }
`;

3. 使用方式

c 复制代码
// 引入组件
import Decimal from '@/components/Decimal'
// 使用
{/* PC端、正数 */}
<Decimal value="888888.00000066666666666600" type="compare" />
{/* PC端、负数 */}
<Decimal value="-888888.00000066666666666600" type="compare" />
{/* PC端、显示所有小数点 */}
<Decimal value="888888.00000066666666666600" display="full" />
{/* 移动端尺寸 */}
<Decimal layout="responsive" value="888888.00000066666666666600" type="compare" />

4. 效果展示


总结

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

相关推荐
心在飞扬1 小时前
ReRank重排序提升RAG系统效果
前端·后端
心在飞扬1 小时前
RAPTOR 递归文档树优化策略
前端·后端
前端Hardy1 小时前
别再无脑用 `JSON.parse()` 了!这个安全漏洞你可能每天都在触发
前端·javascript·vue.js
前端Hardy2 小时前
别再让 `console.log` 上线了!它正在悄悄拖垮你的生产系统
前端·javascript·vue.js
青青家的小灰灰2 小时前
从入门到精通:Vue3 ref vs reactive 最佳实践与底层原理
前端·vue.js·面试
OpenTiny社区2 小时前
我的新同事是个AI:支持skill后,它用TinyVue搭项目还挺溜!
前端·vue.js·ai编程
是你的小橘呀2 小时前
TypeScript在React项目中的实战应用指南
react.js
心在飞扬2 小时前
MultiVector 多向量检索
前端·后端
用户39051332192882 小时前
async 函数返回的 Promise 状态何时变为 resolved
前端
李剑一2 小时前
大屏天气展示太普通?视觉升级!用 Canvas 做动态天气遮罩,雷阵雨效果直接封神
前端·vue.js·canvas