如何将 this.props.onClick() 推迟到 CSS 动画完成之后?
How to defer this.props.onClick() until after a CSS animation is complete?
我正在从我的页面调用自定义 NanoButton
组件以及 onClick
指令以路由到另一个页面:
// Page.js
import { Component } from 'react';
import Router from 'next/router';
class Page2 extends Component {
render() {
return(
<NanoButton type="button" color="success" size="lg" onClick={() => Router.push('/about')}>About</NanoButton>
)
}
}
单击按钮(NanoButton
组件)时,我想在继续作为道具进入的 onClick
之前执行一些内部代码。通过这个内部代码,我试图模拟持续 600 毫秒的 material-设计涟漪效应。我是这样做的:
import { Component } from 'react';
import { Button } from 'reactstrap';
class NanoButton extends Component {
constructor(props) {
super(props);
this.onClick = this.onClick.bind(this);
}
onClick(e) {
this.makeRipple(e);
this.props.onClick();
}
makeRipple(e) {
const elements = e.target.getElementsByTagName('div');
while (elements[0]) elements[0].parentNode.removeChild(elements[0]);
const circle = document.createElement('div');
e.target.appendChild(circle);
const d = Math.max(e.target.clientWidth, e.target.clientHeight);
circle.style.width = `${d}px`;
circle.style.height = `${d}px`;
const rect = e.target.getBoundingClientRect();
circle.style.left = `${e.clientX - rect.left - (d / 2)}px`;
circle.style.top = `${e.clientY - rect.top - (d / 2)}px`;
circle.classList.add('ripple');
}
render() {
return (
<Button
className={this.props.className}
type={this.props.type}
color={this.props.color}
size={this.props.size}
onClick={this.onClick}
>
{this.props.children}
</Button>
);
}
}
export default NanoButton;
因此如您所见,我需要 makeRipple
方法在 this.props.onClick
之前执行。最初,它似乎并没有这样做。然而,经过进一步测试,事实证明这些方法毕竟以正确的顺序执行 运行,除了路由(如 this.props.onClick
中的编码)立即发生并且样式为持续 600 毫秒的涟漪动画没有机会 运行。使这个动画发生的 CSS 是:
button {
overflow: hidden;
position: relative;
}
button .ripple {
border-radius: 50%;
background-color: rgba(255, 255, 255, 0.7);
position: absolute;
transform: scale(0);
animation: ripple 0.6s linear;
}
@keyframes ripple {
to {
transform: scale(2.5);
opacity: 0;
}
}
如何让 this.props.onClick
运行 仅在 之后 动画完成?我试过像这样设置超时:
setTimeout(this.props.onClick(), 600);
但这会引发错误。
注意:我正在使用 NextJS 进行服务器端渲染,如果这有什么不同的话。
有很多方法可以实现,比如Promise
、async/await
等。
但是如果你尝试 setTimeout
请使用
setTimeout(() => this.props.onClick(), 600);
或
setTimeout(this.props.onClick, 600);
您的情况:
setTimeout(this.props.onClick(), 600);
将不起作用,因为此行会将 this.props.onClick()
的结果传递到第一个参数而不是传递整个函数。
我正在从我的页面调用自定义 NanoButton
组件以及 onClick
指令以路由到另一个页面:
// Page.js
import { Component } from 'react';
import Router from 'next/router';
class Page2 extends Component {
render() {
return(
<NanoButton type="button" color="success" size="lg" onClick={() => Router.push('/about')}>About</NanoButton>
)
}
}
单击按钮(NanoButton
组件)时,我想在继续作为道具进入的 onClick
之前执行一些内部代码。通过这个内部代码,我试图模拟持续 600 毫秒的 material-设计涟漪效应。我是这样做的:
import { Component } from 'react';
import { Button } from 'reactstrap';
class NanoButton extends Component {
constructor(props) {
super(props);
this.onClick = this.onClick.bind(this);
}
onClick(e) {
this.makeRipple(e);
this.props.onClick();
}
makeRipple(e) {
const elements = e.target.getElementsByTagName('div');
while (elements[0]) elements[0].parentNode.removeChild(elements[0]);
const circle = document.createElement('div');
e.target.appendChild(circle);
const d = Math.max(e.target.clientWidth, e.target.clientHeight);
circle.style.width = `${d}px`;
circle.style.height = `${d}px`;
const rect = e.target.getBoundingClientRect();
circle.style.left = `${e.clientX - rect.left - (d / 2)}px`;
circle.style.top = `${e.clientY - rect.top - (d / 2)}px`;
circle.classList.add('ripple');
}
render() {
return (
<Button
className={this.props.className}
type={this.props.type}
color={this.props.color}
size={this.props.size}
onClick={this.onClick}
>
{this.props.children}
</Button>
);
}
}
export default NanoButton;
因此如您所见,我需要 makeRipple
方法在 this.props.onClick
之前执行。最初,它似乎并没有这样做。然而,经过进一步测试,事实证明这些方法毕竟以正确的顺序执行 运行,除了路由(如 this.props.onClick
中的编码)立即发生并且样式为持续 600 毫秒的涟漪动画没有机会 运行。使这个动画发生的 CSS 是:
button {
overflow: hidden;
position: relative;
}
button .ripple {
border-radius: 50%;
background-color: rgba(255, 255, 255, 0.7);
position: absolute;
transform: scale(0);
animation: ripple 0.6s linear;
}
@keyframes ripple {
to {
transform: scale(2.5);
opacity: 0;
}
}
如何让 this.props.onClick
运行 仅在 之后 动画完成?我试过像这样设置超时:
setTimeout(this.props.onClick(), 600);
但这会引发错误。
注意:我正在使用 NextJS 进行服务器端渲染,如果这有什么不同的话。
有很多方法可以实现,比如Promise
、async/await
等。
但是如果你尝试 setTimeout
请使用
setTimeout(() => this.props.onClick(), 600);
或
setTimeout(this.props.onClick, 600);
您的情况:
setTimeout(this.props.onClick(), 600);
将不起作用,因为此行会将 this.props.onClick()
的结果传递到第一个参数而不是传递整个函数。