Splitting.js 和 anime.js 等动画库无法在 React JS 上运行

Animation libraries like Splitting.js and anime.js not working on React JS

好的,我已经尝试了 2 个动画库,首先,splitting.js and second anime.js,两者在 vanilla js 上都可以正常工作,但在 react js 上却失败了,知道为什么吗?错误没有意义。请尝试对这两个包进行基本的 npm 安装,并尝试在 react js 项目中使用它们,它们都不起作用。有什么理由吗?以及如何在 React js 中实际使用这些库?我猜它与 React 的 ReactDOM 改变 DOM 元素有关,因此甚至在动画库找到它们之前就删除了所需的元素。

重现我的场景: 请尝试 运行 一个简单的 react js 项目并尝试一个一个地添加这两个动画库

要在您的 React 应用程序中使用 anime.js,您可能需要查看 https://www.npmjs.com/package/react-anime

许多 DOM 操纵库不能开箱即用,因为 React 有自己的做事方式。您可以通过在有效挂钩中执行这些库代码来尝试,而不是在组件声明本身中。

我的想法是使用 react-spring,它是从头开始构建的,考虑到了 React。另一方面,react-anime 只是 anime.js 的包装器,它将其塑造成 react 的生命周期。

在 React 组件上使用 anime.js 时,您需要确保以 DOM 元素为目标,而不是虚拟 DOM 元素。这是一个例子。它有点旧,但是 code/logic 的 afaik none 已被弃用,并且可以使用 useEffect 挂钩轻松转换为功能组件。

import React from 'react';
import ReactDOM from 'react-dom';
import { TransitionGroup, Transition } from 'react-transition-group';
import anime from 'animejs';

import './style.scss';

class ListItem extends React.Component {
    constructor() {
        super();

        // create li DOM reference
        this.liRef = React.createRef();
    }

    componentDidUpdate(){
        this.animeRef = anime({
            targets: this.liRef.current,
            translateX: () => {
                if( this.props.status == 'entering' ) {
                    return ['-100%', '0%'];
                } else if( this.props.status == 'exiting' ) {
                    return ['0%', '100%'];
                }
            },
            elasticity: () => {
                if( this.props.status == 'entering' ) {
                    return 300;
                } else if( this.props.status == 'exiting' ) {
                    return 0;
                }
            },
            duration: 500
        });
    }

    render() {
        return (
            <li className="list-item" ref={ this.liRef }>
                Hey, I am item number <b>{ this.props.num }</b>
            </li>
        );
    }
}

class App extends React.Component {
    constructor() {
        super();

        this.state = {
            data: [1,2,3]
        };
    }

    add() {
        this.setState({
            ...this.state,
            data: this.state.data.concat([ this.state.data.length + 1 ])
        });
    }

    remove() {
        this.setState({
            ...this.state,
            data: this.state.data.slice(0, -1)
        });
    }

    render() {
        return (
            <div className="app-container">
                <div className="buttons">
                    <button onClick={ this.add.bind(this) }>Add one</button>
                    <button onClick={ this.remove.bind(this) }>Remove one</button>
                </div>

                <TransitionGroup 
                component="ul"
                className="list"
                >
                    {
                        this.state.data.map( num => (
                            <Transition 
                            key={ num }
                            timeout={ 500 }
                            mountOnEnter
                            unmountOnExit
                            >
                                {
                                    ( status ) => {
                                        return <ListItem status={ status } num={ num }/>;
                                    }
                                }
                            </Transition>
                        ) )
                    }
                </TransitionGroup>
            </div>
        );
    }
}

ReactDOM.render(<App />, document.getElementById('app'));

示例来自 this 文章,如果您想了解有关此事的更多信息。

如果你只是想在 codesandbox

中打耳光,这里是 style.scss