在react中,我们主要使用react-transition-group实现动画过度效果,本文将讨论如何在react项目中实现过度动画效果。
安装
# npm
npm install react-transition-group --save
# yarn
yarn add react-transition-group
官方提供的三个组建Transition
,CSSTransition
,TransitonGroup
。
使用
1.Transition
过渡组件(Transiton)允许您用一个简单的声明性API描述随着时间的推移从一个组件状态到另一个组件状态的转换。最常用的是用来动画一个组件的安装和卸载,但也可以用来描述在适当的过渡状态。默认情况下,该组件不会更改其呈现的组件的行为,它只跟踪组件的“进入”和“退出”的状态。由你来为这些状态定义效果。
//自己简单的封装了一个,该有的参数都由了,可以自行粘贴在自己的代码里面去试试。
class Fade extends React.Component {
constructor(props) {
super(props);
}
done =() => {
// console.log('结束了')
}
addaddEndListener = (node) => { //原生时间transition运动的事件
node.addEventListener('transitionend', this.done, false);
}
// 三个进入状态的事件,可以做你想做的事情
onEnter = (node, isAppearing) => {
console.log(isAppearing, 'onEnter')
}
onEntering = (node, isAppearing) => {
console.log(isAppearing, 'onEntering')
}
onEntered = (node, isAppearing) => {
console.log(isAppearing, 'onEntered')
}
// 三个退出的状态的事件
onExit = (node) => {
console.log('onExit')
}
onExiting = () => {
console.log('onExiting')
}
onExited = () => {
console.log('onExited')
this.props.self()
}
render() {
const { in: inProp, dur} = this.props;
const defaultStyle = {
transition: `transform ${300}ms ease-in-out, opacity ${300}ms ease-in-out`,
transform: 'translateX(100px)',
opacity: '0'
}
const transitionStyles = {
entering: { transform: 'translateX(100px)', opacity: '0'},
entered: { transform: 'translateX(0px)', opacity: '1' },
exiting: {transform: 'translateX(0px)', opacity: '1'},
exited: {transform: 'translateX(0px)', opacity: '0'}
};
const duration = {
enter: 300,
exit: 300,
}
// 上面的都是基本参数,样式的转变以及时间的设定,具体的可以看官网文档
// 样式也可以写成className 例如<MyComponent className={`fade fade-${status}`} />
return (
<Transition
onEnter={this.onEnter}
onEntering={this.onEntering}
onEntered={this.onEntered}
onExit={this.onExit}
onExiting={this.onExiting}
onExited={this.onExited}
addEndListener={this.addaddEndListener}
in={inProp}
unmountOnExit={false} // 为true 代表退出的时候移除dom
appear={true} // 为true 渲染的时候就直接执行动画,默认false,
timeout={duration}
>
{
state => {
console.log(state, '###') //你可以很直观的看到组件加载和卸载时候的状态
return(
<div style={{
...defaultStyle,
...transitionStyles[state]
}}>
{this.props.children}
</div>
)
}
}
</Transition>
);
}
}
Transition
组件本身不会对其子组件执行任何操作。它所做的是跟踪一段时间内的转换状态,以便在更改状态时更新组件(例如通过添加样式或类)。
Transition可以有4种主要状态:
entering
entered
exiting
exited
//组件的初始化状态都停留在exited
调用方法:
let num = 1;
class Dnd extends React.Component {
state = {
ins: true,
current: 1,
dom: <div className={l.test}>
ceshi weizhi {num}
</div>
}
handle = (bool) => {
this.setState({
test: !bool
})
}
end = () => {
const that = this;
num = num + 1;
setTimeout(function () {
that.setState({
test: true,
dom: <div className={l.test}>
888888 {num}
</div>
})
}, 500)
}
render () {
const { location } = this.props
const { test } = this.state;
return (
<MainLayout location={location}>
<Button onClick={this.handle.bind(null, this.state.test)}>点击transition</Button>
<Fade in={this.state.test} self={this.end}>
{this.state.dom}
</Fade>
</MainLayout>
)
}
}
// 效果是每次点击按钮都会进行一次进场和出场的动画。也可以自行衍生。
2.CSSTransition
class Example extends Component{
state={
isShow:true
}
render(){
return (
<div>
<h2>CSSTransition</h2>
<CSSTransition
in={this.state.isShow}
classNames="message"
unmountOnExit//是否占茅坑
timeout={5000}//消失延迟
appear = {true}
>
{
<div className="box">看我秀你一脸狗屎</div>
}
</CSSTransition>
<p><button onClick= {() => this.setState({isShow: !this.state.isShow})}>toggle</button></p>
</div>
)
}
}
相对应的钩子函数如下:
classNames={{
appear: 'my-appear',
appearActive: 'my-active-appear',
enter: 'my-enter',
enterActive: 'my-active-enter',
enterDone: 'my-done-enter,
exit: 'my-exit',
exitActive: 'my-active-exit',
exitDone: 'my-done-exit,
}}
附相关css:
.message-enter, .message-appear {
opacity: 0;
/* transform: scale(0.9) translateY(50%); */
}
.message-enter-active, .message-appear-active {
opacity: 1;
/* transform: scale(1) translateY(0%); */
transition: all 1000ms ease-out;
}
.message-enter-done {
opacity: 1;
}
.message-exit {
opacity: 1;
/* transform: scale(1) translateY(0%); */
}
.message-exit-active {
opacity: 0.01;
/* transform: scale(0.9) translateY(50%); */
transition: all 1000ms ease-out;
}
.message-exit-done {
opacity: 0;
/* transform: scale(1) translateY(0%); */
}
3.TransitionGroup
class Example extends Component{
state = {
isShow: true,
items: [
{id: uuid(), text: 'Hello World'},
{id: uuid(), text: 'Hello React'},
]
}
render () {
return (
<div>
<TransitionGroup>
{
this.state.items.map(item => (
<CSSTransition
key = {item.id}
timeout = {1000}
classNames = "message"
unmountOnExit
>
{
(state) => (<h3 >{item.text} -- {state}</h3>)
}
</CSSTransition>
))
}
</TransitionGroup>
<p><button onClick= {() => {
this.setState({
items: [ ...this.state.items, {
id: uuid(), text: 'new Hello'
}]
})
}}>add</button></p>
</div>
)
}
}
(css同第二部分)
请注意,
<TransitionGroup>
没有定义任何动画行为!究竟如何列表项动画是由个人<Transition>
组成部分。