如何将this.props.onClick()推迟到CSS动画完成之后? [英] How to defer this.props.onClick() until after a CSS animation is complete?

查看:203
本文介绍了如何将this.props.onClick()推迟到CSS动画完成之后?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在从页面中调用自定义的NanoButton组件以及onClick指令以路由到另一个页面:

I am calling a custom NanoButton component from my page along with an onClick instruction to route to another page:

// 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毫秒的材质设计波纹效果.这是我的方法:

When the button (NanoButton component) is clicked, I want to execute some internal code before moving on to the onClick coming in as props. Through this internal code, I am trying to simulate the material-design ripple effect that lasts 600 milliseconds. This is how I do it:

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;

因此,如您所见,我需要在this.props.onClick之前执行makeRipple方法.最初,它似乎并没有这样做.但是,经过进一步测试,结果证明这些方法毕竟会按正确的顺序运行,除了路由(如this.props.onClick中所编码的)会立即发生并且样式为持续600毫秒的波纹动画没有机会跑步.使该动画发生的CSS是:

So as you can see, I need the makeRipple method to execute before this.props.onClick. And initially, it didn't seem to doing that. However, after further testing, it turns out that the methods do run in the right order after all, except the routing (as coded in this.props.onClick) happens instantly and the ripple animation that's styled to last 600 milliseconds doesn't get a chance to run. The CSS that makes this animation happen is:

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仅在之后播放动画?我试图像这样设置超时时间:

How do I make the this.props.onClick run only AFTER the animation is complete? I tried setting a timeout like so:

setTimeout(this.props.onClick(), 600);

但这会引发错误.

注意:我在服务器端使用 NextJS 渲染,如果有什么区别.

Note: I'm using NextJS for server side rendering, if that makes any difference.

推荐答案

有很多方法可以做到,例如Promiseasync/await等. 但是,如果您尝试setTimeout,请使用

There are a lot of ways to do it, like Promise, async/await, etc. But if you try setTimeout please use

setTimeout(() => this.props.onClick(), 600);

setTimeout(this.props.onClick, 600);

您的情况:

setTimeout(this.props.onClick(), 600);

无效,因为此行会将this.props.onClick()的结果传递给第一个参数,而不是传递整个函数.

won't work because this line will pass the result of this.props.onClick() into the first param instead of passing the whole function.

这篇关于如何将this.props.onClick()推迟到CSS动画完成之后?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆