react之动画transtion-group

83 阅读2分钟
官网
一些组件和props
  • Transtion
  • CSSTransition
  • SwitchTransition
  • TransitionGroup
使用注意事项
  1. SwitchTranstion 中要包一个CSSTransition组件,不能直接包子组件
  2. TransitionGroup 组件中需要包 多个组件的集合,CSSTranstion 则只能包一个组件

具体例子

  1. 显示与隐藏状态切换的动画

使用CSSTranstion 包裹子元素,同时给CSSTranstion 组件设置in,className等属性

import { useState } from 'react';
import { CSSTransition } from 'react-transition-group';
import "./index.css";
import { Button } from 'antd';

function TransitionDemo() {
  const [show, setShow] = useState(false);
  return <div>
    <CSSTransition in={show} timeout={2000} classNames="fade">
      <div className='box'></div>
    </CSSTransition>
    <Button onClick={() => setShow(!show)}>{!show ? '进入': '离开'}</Button>
  </div>
}

export default TransitionDemo;

index.css

.box {
    width: 100px;
    height: 100px;
    background-color: orange;
    border-radius: 24px;
}

.fade-enter {
    opacity: 0;
    transform: translateX(100%);
}

.fade-enter-active {
    opacity: 1;
    transform: translateX(0);
    transition: all 0.5s;
}

.fade-enter-done {
    opacity: 1;
    transform: translateX(0);
    transition: all 0.5s;
}

.fade-exit {
    opacity: 1;
    transform: translateX(0);
}

.fade-exit-active {
    opacity: 0;
    transform: translateX(100%);
    transition: all 0.5s;
}

.fade-exit-done {
    opacity: 0;
    transform: translateX(100%);
    transition: all 0.5s;
}

  1. 两个组件切换的动画。(就是隐藏和展示几乎同时出现的动画,一个组件隐藏或者销毁,另一个组件随后立刻显示或者创建,或者新组件先显示,旧组件再隐藏或者销毁)
import { PureComponent, ReactNode } from 'react';
import { SwitchTransition, CSSTransition } from 'react-transition-group';
import './switch.scss';

export default class SwitchAnimation extends PureComponent<any, any> {
    constructor(props: any) {
        super(props);
        this.state = {
            isOn: true,
        }
    }

    btnClick() {
        this.setState({
            isOn: !this.state.isOn,
        });
    }

    render(): ReactNode {
        const { isOn } = this.state;
        // out-in 表示旧组件先移除,新组件再进入
        return (
            <SwitchTransition mode='out-in'>
                <CSSTransition timeout={500}
                    classNames={'btn'} key={isOn ? 'on' : 'off'}>
                    {
                        <button onClick={this.btnClick.bind(this)}>
                            {isOn ? 'on' : 'off'}
                        </button>
                    }
                </CSSTransition>
            </SwitchTransition>
        )
    }
}

switch.scss

.btn-enter {
    transform: translate(100%, 0);
    opacity: 0;
}

.btn-enter-active {
    transform: translate(0, 0);
    opacity: 1;
    transition: all 500ms;
}

.btn-exit {
    transform: translate(0, 0);
    opacity: 1;
}

.btn-exit-active {
    transform: translate(-100%, 0);
    opacity: 0;
    transition: all 500ms;
}
  1. 一组动画,插入节点,或者删除节点的动画
import { Button } from 'antd';
import React, { PureComponent } from 'react';
import './group2.scss';

import { CSSTransition, TransitionGroup } from 'react-transition-group';

export default class GroupAnimation extends PureComponent<any, any> {
    constructor(props: any) {
        super(props);
        this.state = {
            friends: [],
            count: 0,
        };
    }

    addFriend = () => {
        this.setState({
            friends: [...this.state.friends, "coderwhy"]
        });
    };

    removeFriend = () => {
        const newFriends = JSON.parse(JSON.stringify(this.state.friends));
        newFriends.length = newFriends.length - 1;
        this.setState({
            friends: [
                ...newFriends,
            ]
        })
    };

    incrCount = () => {
        // 传递一个函数,也是异步
        // 只是传递函数的时候,不会将更改进行合并了
        this.setState((state: any) => ({ ...state, count: state.count + 1}));
        console.log('this.state.count', this.state.count);
        this.setState((state: any) => ({ ...state, count: state.count + 1}));
        console.log('this.state.count', this.state.count);
    }


    // TransitionGroup
    render(): React.ReactNode {
        const { count } = this.state;
        return (
            <div>
                <TransitionGroup>
                {
                    this.state.friends.map((item: any, index: number) => {
                        return (
                            <CSSTransition classNames={'friend'}  timeout={300}>
                                <div>{item}</div>
                            </CSSTransition>
                        )
                    })
                }
                </TransitionGroup>
                <h1>{count}</h1>
                <Button onClick={this.incrCount}>增加count值</Button>
                <Button onClick={(e) => this.addFriend()}>+friend</Button>
                <Button onClick={(e) => this.removeFriend()}>-friend</Button>
            </div>
        )
    }
}

group2.css

.friend-enter {
    transform: translate(100%, 0);
    opacity: 0;
}

.friend-enter-active {
    transform: translate(0, 0);
    opacity: 1;
    transition: all 500ms;
}

.friend-exit {
    transform: translate(0, 0);
    opacity: 1;
}

.friend-exit-active {
    transform: translate(-100%, 0);
    opacity: 0;
    transition: all 500ms;
}