在 react 里,有个专门的库是用来处理动画的,那就是 react-transition-group
js 部分如下
import React, { Component, Fragment } from "react";
import { CSSTransition } from "react-transition-group"; // 引入组件
import "./style.css";
class TransitionGroup extends Component {
constructor(props) {
super(props);
this.state = {
show: true
};
this.clickBtn = this.clickBtn.bind(this);
}
render() {
const { show } = this.state;
return (
<Fragment>
<CSSTransition
in={show} // 切换 class 的控制器
timeout={500} // 过渡时间
classNames="fade" // 过渡 class 名称前缀
unmountOnExit // 如果需要移除该 DOM,可以加此属性
onEntered={el => (el.style.color = "blue")} // 动画钩子
appear={true} // 第一次显示的时候是否做动画1
>
<div className="box">我是一个盒子</div>
</CSSTransition>
<button className="btn" onClick={this.clickBtn}>
点击我
</button>
</Fragment>
);
}
clickBtn() {
this.setState(prev => ({
show: !prev.show
}));
}
}
export default TransitionGroup;
css 部分如下
.box {
width: 100px;
height: 100px;
background: lightblue;
color: white;
font-size: 12px;
line-height: 100px;
text-align: center;
border-radius: 4px;
transition: all 0.4s ease;
}
.btn {
width: 100px;
line-height: 30px;
border: none;
background: lightcoral;
margin-top: 10px;
border-radius: 4px;
color: white;
outline: none;
}
/* 入场开始 首次进场开始 */
.fade-enter, .fade-appear {
opacity: 0;
}
/* 入场过程 首次进场过程 */
.fade-enter-active, .fade-appear-active {
opacity: 1;
transition: all 0.5s ease;
}
/* 入场结束 */
.fade-enter-done {
opacity: 1;
}
/* 出场开始 */
.fade-exit {
opacity: 1;
}
/* 出场过程 */
.fade-exit-active {
opacity: 0;
transition: all 0.5s ease;
}
/* 出场结束 */
.fade-exit-done {
opacity: 0;
}
这样,一个动画就完成了
如果动画是循环的组件,可以使用 TransitionGroup
js 部分如下
import React, { Component, Fragment } from "react";
import { TransitionGroup, CSSTransition } from "react-transition-group";
import "./ref-comp.css";
class InputComp extends Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
const { inputEle, changeInput, value } = this.props;
return <input ref={inputEle} onChange={changeInput} value={value} />;
}
}
class ListItem extends Component {
constructor(props) {
super(props);
this.state = {};
}
shouldComponentUpdate(prevState) {
return prevState !== this.props;
}
render() {
const { item, index, removeItem } = this.props;
return <li onClick={removeItem.bind(this, index)}>{item}</li>;
}
}
class RefComp extends Component {
constructor(props) {
super(props);
this.state = {
list: ["123", "234"],
inputValue: ""
};
this.inputEle = null;
this.removeItem = this.removeItem.bind(this);
}
render() {
return (
<Fragment>
<InputComp
inputEle={el => (this.inputEle = el)}
changeInput={this.changeInput}
value={this.state.inputValue}
></InputComp>
<button onClick={this.addList}>增加</button>
<ul>
<TransitionGroup>{this.getList()}</TransitionGroup>
</ul>
</Fragment>
);
}
getList = () => {
return this.state.list.map((item, index) => {
return (
// 暂时不知道怎么做移除的退出动画,先留个标注,后面解决了再回来补上。
<CSSTransition
key={index}
in={true}
classNames="fade"
timeout={500}
appear={true}
>
<ListItem index={index} item={item} removeItem={this.removeItem} />
</CSSTransition>
);
});
};
removeItem = index => {
let list = [...this.state.list];
list.splice(index, 1);
this.setState({ list });
};
changeInput = () => {
let value = this.inputEle.value;
this.setState(_ => ({
inputValue: value
}));
};
addList = () => {
this.setState(prev => ({
list: [...prev.list, this.state.inputValue],
inputValue: ""
}));
};
}
export default RefComp;
css 部分如下
.fade-enter,
.fade-appear {
opacity: 0;
}
.fate-enter-active,
.fade-appear-active {
opacity: 1;
transition: all 0.5s ease;
}
.fade-exit {
opacity: 1;
}
.fade-exit-active {
opacity: 0;
}