Antd Alert 组件

源码地址

这个组件相对简单,就是一个布局组件

传参

/** 简化后的属性 **/
export interface AlertProps {
  type?: 'success' | 'info' | 'warning' | 'error';
  message?: React.ReactNode;
  description?: React.ReactNode;
  onClose?: React.MouseEventHandler<HTMLButtonElement>;
  afterClose?: () => void;
  showIcon?: boolean;
  icon?: React.ReactNode;
}

其实也就是一个用CSSMotion 包裹住的div 组件, 里面渲染了message. description, 等

<CSSMotion
    visible={!closed}
    motionName={`${prefixCls}-motion`}
    motionAppear={false}
    motionEnter={false}
    onLeaveStart={node => ({
    maxHeight: node.offsetHeight,
    })}
    onLeaveEnd={afterClose}
>
    {({ className: motionClassName, style: motionStyle }) => (
    <div
            ref={ref}
            className={classNames(alertCls, motionClassName)}
            style={{ ...style, ...motionStyle }}
            {...props}
    >
            {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>

值得学习的地方是,renderIconNode 函数

const renderIconNode = () => {
    const { icon } = props;
    // 这里源码中 iconMapOutlined 是一个map, 里面是一个 { [type: string]: AntdIcon } 
    const iconType = (description ? iconMapOutlined : iconMapFilled)[type] || null;
    if (icon) {
        /** 这里replaceElement 其实源码是用 React.cloneElement 去实现的, 
            * 就是判断icon 是否是element 不是的话就用第二参数, 是的话就克隆element,然后添加其余属性 
            */
        return replaceElement(icon, <span className={`${prefixCls}-icon`}>{icon}</span>, () => ({
            className: classNames(`${prefixCls}-icon`, {
                [(icon as any).props.className]: (icon as any).props.className,
            }),
        }));
    }
    /** 这里如果是自己写的话, 是用一个div 去包裹着, 而不是像他那样创建一个element, 这里如果换成React.cloneElement是不是更加合适? */
    return React.createElement(iconType, { className: `${prefixCls}-icon` });
  };