Ant Design是React生态中一个高质量的UI组件库, 本文带领大家深入了解最经典的Button在 Antd 中是如何实现的。
首先让我们看一下按钮的点击事件处理函数handleClick
handleClick = (e) => {
this.setState({ clicked: true });
clearTimeout(this.timeout);
this.timeout = setTimeout(() => this.setState({ clicked: false }), 500);
const onClick = this.props.onClick;
if (onClick) {
onClick(e);
}
}
那么点击了按钮后发生了什么?
clicked
为true
clicked
设置为false
, 用来re-render。onClick
则在事件发生时, 调用onClick
componentWillReceiveProps(nextProps) {
const currentLoading = this.props.loading;
const loading = nextProps.loading;
if (currentLoading) {
clearTimeout(this.delayTimeout);
}
if (loading) {
this.delayTimeout = setTimeout(() => this.setState({ loading }), 200);
} else {
this.setState({ loading });
}
}
componentWillReceiveProps
是用来当props
变化时更新state
的, 但可能即使props
没有改变该生命周期函数也会被调用, 因此我们要确保对比以下props
是否真的有变化。在Antd中给Button传递loading
属性时, Button则会渲染一个转圈的等待动画, 当this.props.loading
发生改变时对loading状态进行判断, 如果网络请求的回应小于200ms则不会渲染等待动画。
componentWillUnmount
生命周期函数在组件将要销毁的时候被调用, 一般用于做一些清理工作比如清理定时器, 网络请求, 亦或者与其它库的交互。
componentWillUnmount() {
if (this.timeout) {
clearTimeout(this.timeout);
}
if (this.delayTimeout) {
clearTimeout(this.delayTimeout);
}
}
Button中使用了timeout
和delayTimeout
2个定时器, timeout
用于0.5秒后复位点击状态clicked
, delayTimeout
用于清理延时加载loading动画的定时器。
Antd使用TypeScript开发, 通过interface我们可以对组件的使用进行约束, 可以帮助我们快速定位组件参数传递错误导致的Bug
export interface ButtonProps {
type?: ButtonType;
htmlType?: string;
icon?: string;
shape?: ButtonShape;
size?: ButtonSize;
onClick?: React.FormEventHandler<any>;
onMouseUp?: React.FormEventHandler<any>;
loading?: boolean;
disabled?: boolean;
style?: React.CSSProperties;
prefixCls?: string;
className?: string;
ghost?: boolean;
}
export default class Button extends React.Component<ButtonProps, any> {
}
这似乎与PropTypes
的检测重复了
export default class Button extends React.Component<ButtonProps, any> {
static propTypes = {
type: React.PropTypes.string,
shape: React.PropTypes.oneOf(['circle', 'circle-outline']),
size: React.PropTypes.oneOf(['large', 'default', 'small']),
htmlType: React.PropTypes.oneOf(['submit', 'button', 'reset']),
onClick: React.PropTypes.func,
loading: React.PropTypes.bool,
className: React.PropTypes.string,
icon: React.PropTypes.string,
};