2021SC@SDUSC
源码分析如下
1.导入相应模块以及相应的ICON图标
import CloseOutlined from '@ant-design/icons/CloseOutlined';
import CheckCircleOutlined from '@ant-design/icons/CheckCircleOutlined';
import ExclamationCircleOutlined from '@ant-design/icons/ExclamationCircleOutlined';
import InfoCircleOutlined from '@ant-design/icons/InfoCircleOutlined';
import CloseCircleOutlined from '@ant-design/icons/CloseCircleOutlined';
import CheckCircleFilled from '@ant-design/icons/CheckCircleFilled';
import ExclamationCircleFilled from '@ant-design/icons/ExclamationCircleFilled';
import InfoCircleFilled from '@ant-design/icons/InfoCircleFilled';
import CloseCircleFilled from '@ant-design/icons/CloseCircleFilled';
import CSSMotion from 'rc-motion';
import classNames from 'classnames';
创建了 AlertProps接口
我们看到分别有success、info、warning、error四种种类
属性closeable为boolean类型,表示警告窗口是否可以关闭
closeText、message、description分别为替代关闭按钮的文本、警告正文、警告的额外描述,且均为ReacrtNode类型
type ReactNode = ReactChild | ReactFragment | ReactPortal | boolean | null | undefined;
onClose:鼠标悬浮在关闭钮上的事件
afterClose:关闭后时间,默认为空
showIcon:是否显示图标 style:CSS格式 prefixCls:前缀 className类名 banner:横幅提醒(上端) icon:图标 action:对应的动作 onMouseEnter:鼠标划入发生的事件 onMouseLeave:鼠标划出的事件 onClick:鼠标点击的事件
export interface AlertProps {
/** Type of Alert styles, options:`success`, `info`, `warning`, `error` */
type?: 'success' | 'info' | 'warning' | 'error';
/** Whether Alert can be closed */
closable?: boolean;
/** Close text to show */
closeText?: React.ReactNode;
/** Content of Alert */
message?: React.ReactNode;
/** Additional content of Alert */
description?: React.ReactNode;
/** Callback when close Alert */
onClose?: React.MouseEventHandler<HTMLButtonElement>;
/** Trigger when animation ending of Alert */
afterClose?: () => void;
/** Whether to show icon */
showIcon?: boolean;
/** https://www.w3.org/TR/2014/REC-html5-20141028/dom.html#aria-role-attribute */
role?: string;
style?: React.CSSProperties;
prefixCls?: string;
className?: string;
banner?: boolean;
icon?: React.ReactNode;
action?: React.ReactNode;
onMouseEnter?: React.MouseEventHandler<HTMLDivElement>;
onMouseLeave?: React.MouseEventHandler<HTMLDivElement>;
onClick?: React.MouseEventHandler<HTMLDivElement>;
}
四种类型的填充样式
const iconMapFilled = {
success: CheckCircleFilled,
info: InfoCircleFilled,
error: CloseCircleFilled,
warning: ExclamationCircleFilled,
};
const iconMapOutlined = {
success: CheckCircleOutlined,
info: InfoCircleOutlined,
error: CloseCircleOutlined,
warning: ExclamationCircleOutlined,
};
通过接口实现了Alert
const Alert: AlertInterface = ({
description,
prefixCls: customizePrefixCls,
message,
banner,
className = '',
style,
onMouseEnter,
onMouseLeave,
onClick,
afterClose,
showIcon,
closable,
closeText,
action,
...props
}) => {
手动关闭函数,将alert设为可被关闭
const handleClose = (e: React.MouseEvent<HTMLButtonElement>) => {
setClosed(true);
props.onClose?.(e);
};
获取种类函数,获取alert下的props,若其不为未定义状态则直接返回,否则返回banner的模式
const getType = () => {
const { type } = props;
if (type !== undefined) {
return type;
}
// banner 模式默认为警告
return banner ? 'warning' : 'info';
};
获取alert的图标节点,获取alert下props若存在则返回icon,否则返回一个新element
const renderIconNode = () => {
const { icon } = props;
// use outline icon in alert with description
const iconType = (description ? iconMapOutlined : iconMapFilled)[type] || null;
if (icon) {
return replaceElement(icon, <span className={`${prefixCls}-icon`}>{icon}</span>, () => ({
className: classNames(`${prefixCls}-icon`, {
[(icon as any).props.className]: (icon as any).props.className,
}),
}));
}
return React.createElement(iconType, { className: `${prefixCls}-icon` });
};
与上一个类似,获取关闭图标,存在则返回一个button,否则返回null
const renderCloseIcon = () =>
isClosable ? (
<button
type="button"
onClick={handleClose}
className={`${prefixCls}-close-icon`}
tabIndex={0}
>
{closeText ? (
<span className={`${prefixCls}-close-text`}>{closeText}</span>
) : (
<CloseOutlined />
)}
</button>
) : null;
最后是对alert的样式进行修改
return (
<CSSMotion
visible={!closed}
motionName={`${prefixCls}-motion`}
motionAppear={false}
motionEnter={false}
onLeaveStart={node => ({
maxHeight: node.offsetHeight,
})}
onLeaveEnd={afterClose}
>
{({ className: motionClassName, style: motionStyle }) => (
<div
ref={ref}
data-show={!closed}
className={classNames(alertCls, motionClassName)}
style={{ ...style, ...motionStyle }}
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
onClick={onClick}
role="alert"
{...dataOrAriaProps}
>
{isShowIcon ? renderIconNode() : null}
<div className={`${prefixCls}-content`}>
{message ? <div className={`${prefixCls}-message`}>{message}</div> : null}
{description ? <div className={`${prefixCls}-description`}>{description}</div> : null}
</div>
{action ? <div className={`${prefixCls}-action`}>{action}</div> : null}
{renderCloseIcon()}
</div>
)}
</CSSMotion>
);
};