mirror of
https://github.com/ant-design/ant-design.git
synced 2025-08-06 07:56:28 +08:00
Refactor button click effect implementation
for better perfermance
This commit is contained in:
parent
45fb83d64c
commit
b4d95f7e20
@ -2,6 +2,7 @@ import * as React from 'react';
|
||||
import { findDOMNode } from 'react-dom';
|
||||
import * as PropTypes from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
import clickAnimation from './clickAnimation';
|
||||
import Icon from '../icon';
|
||||
import Group from './button-group';
|
||||
|
||||
@ -86,20 +87,22 @@ export default class Button extends React.Component<ButtonProps, any> {
|
||||
block: PropTypes.bool,
|
||||
};
|
||||
|
||||
timeout: number;
|
||||
delayTimeout: number;
|
||||
clickAnimation: {
|
||||
cancel: () => void;
|
||||
};
|
||||
|
||||
constructor(props: ButtonProps) {
|
||||
super(props);
|
||||
this.state = {
|
||||
loading: props.loading,
|
||||
clicked: false,
|
||||
hasTwoCNChar: false,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.fixTwoCNChar();
|
||||
this.clickAnimation = clickAnimation(findDOMNode(this) as HTMLElement);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps: ButtonProps) {
|
||||
@ -122,12 +125,12 @@ export default class Button extends React.Component<ButtonProps, any> {
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.timeout) {
|
||||
clearTimeout(this.timeout);
|
||||
}
|
||||
if (this.delayTimeout) {
|
||||
clearTimeout(this.delayTimeout);
|
||||
}
|
||||
if (this.clickAnimation) {
|
||||
this.clickAnimation.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
fixTwoCNChar() {
|
||||
@ -148,12 +151,7 @@ export default class Button extends React.Component<ButtonProps, any> {
|
||||
}
|
||||
|
||||
handleClick: React.MouseEventHandler<HTMLButtonElement | HTMLAnchorElement> = e => {
|
||||
// Add click effect
|
||||
this.setState({ clicked: true });
|
||||
clearTimeout(this.timeout);
|
||||
this.timeout = window.setTimeout(() => this.setState({ clicked: false }), 500);
|
||||
|
||||
const onClick = this.props.onClick;
|
||||
const { onClick } = this.props;
|
||||
if (onClick) {
|
||||
(onClick as React.MouseEventHandler<HTMLButtonElement | HTMLAnchorElement>)(e);
|
||||
}
|
||||
@ -169,7 +167,7 @@ export default class Button extends React.Component<ButtonProps, any> {
|
||||
type, shape, size, className, children, icon, prefixCls, ghost, loading: _loadingProp, block, ...rest
|
||||
} = this.props;
|
||||
|
||||
const { loading, clicked, hasTwoCNChar } = this.state;
|
||||
const { loading, hasTwoCNChar } = this.state;
|
||||
|
||||
// large => lg
|
||||
// small => sm
|
||||
@ -190,7 +188,6 @@ export default class Button extends React.Component<ButtonProps, any> {
|
||||
[`${prefixCls}-${sizeCls}`]: sizeCls,
|
||||
[`${prefixCls}-icon-only`]: !children && icon,
|
||||
[`${prefixCls}-loading`]: loading,
|
||||
[`${prefixCls}-clicked`]: clicked,
|
||||
[`${prefixCls}-background-ghost`]: ghost,
|
||||
[`${prefixCls}-two-chinese-chars`]: hasTwoCNChar,
|
||||
[`${prefixCls}-block`]: block,
|
||||
|
20
components/button/clickAnimation.tsx
Normal file
20
components/button/clickAnimation.tsx
Normal file
@ -0,0 +1,20 @@
|
||||
import TransitionEvents from 'css-animation/lib/Event';
|
||||
|
||||
const clickAnimation = (node: HTMLElement) => {
|
||||
function handler() {
|
||||
node.removeAttribute('ant-click-animating');
|
||||
node.setAttribute('ant-click-animating', 'true');
|
||||
TransitionEvents.addEndEventListener(node, () => {
|
||||
node.removeAttribute('ant-click-animating');
|
||||
TransitionEvents.removeEndEventListener(node);
|
||||
});
|
||||
}
|
||||
node.addEventListener('click', handler, false);
|
||||
return {
|
||||
cancel: () => {
|
||||
node.removeEventListener('click', handler, false);
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export default clickAnimation;
|
@ -8,6 +8,7 @@
|
||||
@btn-ghost-color: @text-color;
|
||||
@btn-ghost-bg: transparent;
|
||||
@btn-ghost-border: @border-color-base;
|
||||
@btn-animation-width: 6px;
|
||||
|
||||
// Button styles
|
||||
// -----------------------------
|
||||
@ -131,21 +132,7 @@
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
&-clicked:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -1px;
|
||||
left: -1px;
|
||||
bottom: -1px;
|
||||
right: -1px;
|
||||
border-radius: inherit;
|
||||
border: 0 solid @primary-color;
|
||||
opacity: 0.4;
|
||||
animation: buttonEffect .4s;
|
||||
display: block;
|
||||
}
|
||||
|
||||
&-danger&-clicked:after {
|
||||
&-danger[ant-click-animating]:after {
|
||||
border-color: @btn-danger-color;
|
||||
}
|
||||
|
||||
@ -180,11 +167,11 @@
|
||||
@keyframes buttonEffect {
|
||||
to {
|
||||
opacity: 0;
|
||||
top: -6px;
|
||||
left: -6px;
|
||||
bottom: -6px;
|
||||
right: -6px;
|
||||
border-width: 6px;
|
||||
top: -@btn-animation-width;
|
||||
left: -@btn-animation-width;
|
||||
bottom: -@btn-animation-width;
|
||||
right: -@btn-animation-width;
|
||||
border-width: @btn-animation-width;
|
||||
}
|
||||
}
|
||||
|
||||
@ -197,3 +184,17 @@ a.@{btn-prefix-cls} {
|
||||
line-height: @btn-height-sm - 2px;
|
||||
}
|
||||
}
|
||||
|
||||
[ant-click-animating]:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -1px;
|
||||
left: -1px;
|
||||
bottom: -1px;
|
||||
right: -1px;
|
||||
border-radius: inherit;
|
||||
border: 0 solid @primary-color;
|
||||
opacity: 0.4;
|
||||
animation: buttonEffect .4s cubic-bezier(.25, .8, .25, 1);
|
||||
display: block;
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
exports[`Drawer render correctly 1`] = `
|
||||
<div>
|
||||
<button
|
||||
class="ant-btn ant-btn-clicked"
|
||||
class="ant-btn"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
|
2
typings/custom-typings.d.ts
vendored
2
typings/custom-typings.d.ts
vendored
@ -16,7 +16,7 @@ declare module 'shallowequal';
|
||||
|
||||
declare module 'warning';
|
||||
|
||||
declare module 'css-animation';
|
||||
declare module 'css-animation*';
|
||||
|
||||
declare module 'rc-select';
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user