Ant-design 源码分析之数据展示(二)Badge

2021SC@SDUSC

一、组件结构

1、ant代码结构

2、rc-ant代码结构

3、组件结构

ant中Badge的index.tsx中引入了Ribbon和ScollNumber

index中引用rc-motion做渲染。

二、antd组件调用关系

1、index.tsx
导入相应模块以及相应的ICON图标

import * as React from 'react';
import { useMemo, useRef } from 'react';
import CSSMotion from 'rc-motion';
import classNames from 'classnames';
import ScrollNumber from './ScrollNumber';
import Ribbon from './Ribbon';
import { PresetColorType, PresetStatusColorType } from '../_util/colors';
import { ConfigContext } from '../config-provider';
import { LiteralUnion } from '../_util/type';
import { cloneElement } from '../_util/reactNode';
import { isPresetColor } from './utils';

创建了BadgeProps接口。

showZero:当数值为 0 时,是否展示Badge,类型为boolean。
overflowCount:展示封顶的数字值,类型为number。
dot:不展示数字,只有一个小红点,类型为boolean。
color:自定义小圆点的颜色,类型为string
count:展示的数字,大于 overflowCount 时显示为${overflowCount}+,为 0 时隐藏,类型为ReactNode
offset:设置状态点的位置偏移,类型为[number, number]
size:在设置了 count 的前提下有效,设置小圆点的大小,类型为default | small
status:设置Badge为状态点,类型为success | processing | default | error | warning。
text:在设置了status的前提下有效,设置状态点的文本,类型为ReactNode。
title:设置鼠标放在状态点上时显示的文字,类型为string。

通过接口实现了Badge

const Badge: CompoundedComponent = ({prefixCls: customizePrefixCls,scrollNumberPrefixCls: customizeScrollNumberPrefixCls,children,status,text,color,count = null,overflowCount = 99,dot = false,size = 'default',title,offset,style,className,showZero = false,...restProps
}) => {

设置样式前缀 prefixCls:

  const { getPrefixCls, direction } = React.useContext(ConfigContext);const prefixCls = getPrefixCls('badge', customizePrefixCls);

返回count和overflowcount中较小的值:

  const numberedDisplayCount = ((count as number) > (overflowCount as number) ? `${overflowCount}+` : count) as string | number | null;
//当status或color存在值时返回真:const hasStatus =(status !== null && status !== undefined) || (color !== null && color !== undefined);
//判断是否为0const isZero = numberedDisplayCount === '0' || numberedDisplayCount === 0;const showAsDot = dot && !isZero;const mergedCount = showAsDot ? '' : numberedDisplayCount;
//判断隐藏const isHidden = useMemo(() => {const isEmpty = mergedCount === null || mergedCount === undefined || mergedCount === '';return (isEmpty || (isZero && !showZero)) && !showAsDot;}, [mergedCount, isZero, showZero, showAsDot]);// 防止改变count的值。const countRef = useRef(count);if (!isHidden) {countRef.current = count;}const livingCount = countRef.current;// 防止在改变motion时改变count的值。const displayCountRef = useRef(mergedCount);if (!isHidden) {displayCountRef.current = mergedCount;}const displayCount = displayCountRef.current;const isDotRef = useRef(showAsDot);if (!isHidden) {isDotRef.current = showAsDot;}

设置样式:

  const mergedStyle = useMemo<React.CSSProperties>(() => {if (!offset) {return { ...style };}const offsetStyle: React.CSSProperties = { marginTop: offset[1] };if (direction === 'rtl') {offsetStyle.left = parseInt(offset[0] as string, 10);} else {offsetStyle.right = -parseInt(offset[0] as string, 10);}return {...offsetStyle,...style,};}, [direction, offset, style]);
//设置标题// >>> Titleconst titleNode =title ??(typeof livingCount === 'string' || typeof livingCount === 'number' ? livingCount : undefined);
//设置状态文本// >>> Status Textconst statusTextNode =isHidden || !text ? null : <span className={`${prefixCls}-status-text`}>{text}</span>;
//设置显示组件// >>> Display Componentconst displayNode =!livingCount || typeof livingCount !== 'object'? undefined: cloneElement(livingCount, oriProps => ({style: {...mergedStyle,...oriProps.style,},}));

设置背景颜色:

const statusStyle: React.CSSProperties = {};if (color && !isPresetColor(color)) {statusStyle.background = color;}
//初始化const badgeClassName = classNames(prefixCls,{[`${prefixCls}-status`]: hasStatus,[`${prefixCls}-not-a-wrapper`]: !children,[`${prefixCls}-rtl`]: direction === 'rtl',},className,);

2、ScrollNumber.tsx
导入相应模块以及相应的ICON图标

import * as React from 'react';
import classNames from 'classnames';
import { ConfigContext } from '../config-provider';
import { cloneElement } from '../_util/reactNode';
import SingleNumber from './SingleNumber';

创建了ScrollNumberprops接口和ScrollNumberState接口:

export interface ScrollNumberProps {prefixCls?: string;className?: string;motionClassName?: string;count?: string | number | null;children?: React.ReactElement<HTMLElement>;component?: string;style?: React.CSSProperties;title?: string | number | null;show: boolean;
}

motionClassName:动作类名,类型为string
component:组件,类型为string
show:是否显示,类型为boolean

export interface ScrollNumberState {animateStarted?: boolean;count?: string | number | null;
}

通过接口实现ScrollNumber

const ScrollNumber: React.FC<ScrollNumberProps> = ({prefixCls: customizePrefixCls,count,className,motionClassName,style,title,show,component = 'sup',children,...restProps
}) => {
//初始化const newProps = {...restProps,'data-show': show,style,className: classNames(prefixCls, className, motionClassName),title: title as string,};
 //数字存在时需要移动let numberNodes: React.ReactNode = count;if (count && Number(count) % 1 === 0) {const numberList = String(count).split('');numberNodes = numberList.map((num, i) => (<SingleNumberprefixCls={prefixCls}count={Number(count)}value={num}// eslint-disable-next-line react/no-array-index-keykey={numberList.length - i}/>));}
//边界判断if (style && style.borderColor) {newProps.style = {...style,boxShadow: `0 0 0 1px ${style.borderColor} inset`,};}if (children) {return cloneElement(children, oriProps => ({className: classNames(`${prefixCls}-custom-component`, oriProps?.className, motionClassName),}));}return React.createElement(component as any, newProps, numberNodes);

3、Ribbon.tsx

导入相应模块以及相应的ICON图标

import * as React from 'react';
import classNames from 'classnames';
import { LiteralUnion } from '../_util/type';
import { PresetColorType } from '../_util/colors';
import { ConfigContext } from '../config-provider';
import { isPresetColor } from './utils';

缎带开关

type RibbonPlacement = 'start' | 'end';

创建了RibbonProps接口:

export interface RibbonProps {className?: string;prefixCls?: string;style?: React.CSSProperties; // style of ribbon element, not the wrappertext?: React.ReactNode;color?: LiteralUnion<PresetColorType, string>;children?: React.ReactNode;placement?: RibbonPlacement;
}

color:自定义缎带的颜色,类型为string
placement:缎带的位置,start 和 end 随文字方向(RTL 或 LTR)变动,类型为start | end
text:缎带中填入的内容,类型为ReactNode

实现Ribbon接口:

const Ribbon: React.FC<RibbonProps> = function Ribbon({className,prefixCls: customizePrefixCls,style,color,children,text,placement = 'end',
}) {

设置节点名称

  const { getPrefixCls, direction } = React.useContext(ConfigContext);const prefixCls = getPrefixCls('ribbon', customizePrefixCls);const colorInPreset = isPresetColor(color);const ribbonCls = classNames(prefixCls,`${prefixCls}-placement-${placement}`,{[`${prefixCls}-rtl`]: direction === 'rtl',[`${prefixCls}-color-${color}`]: colorInPreset,},className,);

设置颜色

const colorStyle: React.CSSProperties = {};const cornerColorStyle: React.CSSProperties = {};if (color && !colorInPreset) {colorStyle.background = color;cornerColorStyle.color = color;}

三、rc-antd组件调用关系

1、Rc-motion
CSSmotion

import * as React from 'react';
import { useRef } from 'react';
import findDOMNode from 'rc-util/lib/Dom/findDOMNode';
import { fillRef } from 'rc-util/lib/ref';
import classNames from 'classnames';
import { getTransitionName, supportTransition } from './util/motion';
import type {MotionStatus,MotionEventHandler,MotionEndEventHandler,MotionPrepareEventHandler,
} from './interface';
import { STATUS_NONE, STEP_PREPARE, STEP_START } from './interface';
import useStatus from './hooks/useStatus';
import DomWrapper from './DomWrapper';
import { isActive } from './hooks/useStepQueue';

创建CSSMotionProps接口

export interface CSSMotionProps {motionName?: MotionName;visible?: boolean;motionAppear?: boolean;motionEnter?: boolean;motionLeave?: boolean;motionLeaveImmediately?: boolean;motionDeadline?: number;/*** Create element in view even the element is invisible.* Will patch `display: none` style on it.*/forceRender?: boolean;/*** Remove element when motion end. This will not work when `forceRender` is set.*/removeOnLeave?: boolean;leavedClassName?: string;/** @private Used by CSSMotionList. Do not use in your production. */eventProps?: object;// Prepare groupsonAppearPrepare?: MotionPrepareEventHandler;onEnterPrepare?: MotionPrepareEventHandler;onLeavePrepare?: MotionPrepareEventHandler;// Normal motion groupsonAppearStart?: MotionEventHandler;onEnterStart?: MotionEventHandler;onLeaveStart?: MotionEventHandler;onAppearActive?: MotionEventHandler;onEnterActive?: MotionEventHandler;onLeaveActive?: MotionEventHandler;onAppearEnd?: MotionEndEventHandler;onEnterEnd?: MotionEndEventHandler;onLeaveEnd?: MotionEndEventHandler;// Special/** This will always trigger after final visible changed. Even if no motion configured. */onVisibleChanged?: (visible: boolean) => void;internalRef?: React.Ref<any>;children?: (props: {visible?: boolean;className?: string;style?: React.CSSProperties;[key: string]: any;},ref: (node: any) => void,) => React.ReactElement;
}

Ant-design 源码分析之数据展示(二)Badge相关推荐

  1. Ant Design源码分析(三):Wave组件

    Wave组件效果预览 在上一篇文章Button组件的源码分析中遇到了一个Wave组件, Wave组件在Ant design中提供了通用的表单控件点击效果,在自己阅读源码之前,也并没有过更多留心过在这些 ...

  2. 阿里开源台柱 Ant Design 源码仓库被删了...

    号外,号外,Ant Design 源码仓库被删除! 在广大中国人民还在欢天喜地过新年的时候,Ant Design项目组成员一定是焦头烂额. 因为就在2.15,也就是农历大年初四的时候,一位名叫Jegg ...

  3. Spring 源码分析(四) ——MVC(二)概述

    随时随地技术实战干货,获取项目源码.学习资料,请关注源代码社区公众号(ydmsq666) from:Spring 源码分析(四) --MVC(二)概述 - 水门-kay的个人页面 - OSCHINA ...

  4. 手机自动化测试:appium源码分析之bootstrap十二

    手机自动化测试:appium源码分析之bootstrap十二 poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请 ...

  5. SOFA 源码分析 — 链路数据透传

    前言 SOFA-RPC 支持数据链路透传功能,官方解释: 链路数据透传功能支持应用向调用上下文中存放数据,达到整个链路上的应用都可以操作该数据. 使用方式如下,可分别向链路的 request 和 re ...

  6. Kafka 源码分析之网络层(二)

    上一篇介绍了概述和网络层模型实现<Kafka 源码分析之网络层(一)>,本编主要介绍在Processor中使用的nio selector的又一封装,负责具体数据的接收和发送. PS:丰富的 ...

  7. Spring 源码分析(三) —— AOP(二)Spring AOP 整体架构

    2019独角兽企业重金招聘Python工程师标准>>> Spring AOP 架构         先是生成代理对象,然后是拦截器的作用,最后是编织的具体实现.这是AOP实现的三个步 ...

  8. leveldb源码分析:数据插入续(跳表)

    leveldb数据的插入-跳表 本文主要是接着上一篇文章,继续深入探索Write函数调用插入之后的流程. status = WriteBatchInternal::InsertInto(updates ...

  9. 【NVCaffe源码分析】数据增量之DistortImage

    distort image作为NVCaffe一项常用的数据增量策略,其参数(distort_param)配置大体如下: distort_param {brightness_prob: 0.5brigh ...

最新文章

  1. 2014年Q1中国.BIZ域名总量增1.5万 注册情况稳定
  2. java dateformat 线程安全_SimpleDateFormat线程安全问题深入解析
  3. Spring Security Architecture--官方
  4. 移动领域大话三国(Android/IOS/WP7)之英雄过招
  5. c++中多态---3(虚析构和纯虚析构,向上类型转化和向下类型转化)
  6. html中所有的标签,HTML中的所有标签及其做用!
  7. Supervisor管理hhvm进程
  8. raspberry pi_Raspberry Pi支持的杂耍性能
  9. 【随记】Q号解除限制一波三折
  10. codeforces 719A Vitya in the Countryside(序列判断趋势)
  11. 公司网络需要内网开发,教你如何使内外网同时访问(windows)
  12. OpenMP模式下多线程文件操作 (转)
  13. FISCO BCOS(八)——— 一键部署 WeBase
  14. ajax存储表单数据,使用ajax json将表单数据存储到数据库php
  15. 华为网络技术比赛-note(2018)
  16. pdf转cad怎么弄_CAD转PDF怎么弄?在线老师傅教你一招
  17. ubuntu安装nvidia驱动
  18. 2022年11月多家权威机构____编程语言排行榜__薪酬状况
  19. 高新技术企业申报材料汇编
  20. 使用flv.js实现flv格式的监控视频流播放

热门文章

  1. 蓝桥杯每日一练:纸张尺寸
  2. 天猫代运营公司前十位,国内天猫代运营排行榜
  3. Quectel EC800N-CN 小尺寸物联网首选LTE Cat 1模块[移远通信]
  4. git修改作者信息(提交者信息异常)
  5. 《MATLAB智能算法30个案例》:第14章 基于粒子群算法的PID控制器优化设计
  6. Python交通标志识别基于卷积神经网络的保姆级教程(Tensorflow)
  7. C++ STL编程轻松入门【转载】
  8. android程序键盘锁_适用于Android的最佳键盘应用程序
  9. 超长的Jenkinsfile的Method code too large问题对应方法
  10. 小红书图片剪裁框架+微信图片选择器+超高清大图预览,高级Android程序员必会