动画
React 提供了一个 ReactTransitionGroup
插件作为动画的底层API,和一个 ReactCSSTransitionGroup
用于轻松实现基础的CSS动画和过渡。
高级 API: ReactCSSTransitionGroup
ReactCSSTransitionGroup
基于 ReactTransitionGroup
是一个当React组件进入或离开DOM时,执行CSS动画和过渡的简单方法。它的灵感来自于杰出的 ng-animate 库。
入门指南
ReactCSSTransitionGroup
是 ReactTransitions
的接口。这是一个简单的元素,包裹了所有你感兴趣的动画组件。这里是一个淡入和淡出列表项目的例子。
var ReactCSSTransitionGroup = require('react-addons-css-transition-group');
var TodoList = React.createClass({
getInitialState: function() {
return {items: ['hello', 'world', 'click', 'me']};
},
handleAdd: function() {
var newItems =
this.state.items.concat([prompt('Enter some text')]);
this.setState({items: newItems});
},
handleRemove: function(i) {
var newItems = this.state.items.slice();
newItems.splice(i, 1);
this.setState({items: newItems});
},
render: function() {
var items = this.state.items.map(function(item, i) {
return (
<div key={item} onClick={this.handleRemove.bind(this, i)}>
{item}
</div>
);
}.bind(this));
return (
<div>
<button onClick={this.handleAdd}>Add Item</button>
<ReactCSSTransitionGroup transitionName="example" transitionEnterTimeout={500} transitionLeaveTimeout={300}>
{items}
</ReactCSSTransitionGroup>
</div>
);
}
});
注意:
你必须为
ReactCSSTransitionGroup
的所有子级提供key
属性,即使只渲染一个项目。这就是React将决定哪一个子级进入,离开,或者停留
在这个组件,当一个新的项目被添加到 ReactCSSTransitionGroup
,他将得到example-enter
CSS类 并且在下一刻example-enter-active
CSS类被添加。这是一个基于transitionName
prop 的约定。
你可以使用这些类来触发CSS动画和过渡。比如,尝试添加这个CSS和添加一个新的列表项:
.example-enter {
opacity: 0.01;
}
.example-enter.example-enter-active {
opacity: 1;
transition: opacity 500ms ease-in;
}
.example-leave {
opacity: 1;
}
.example-leave.example-leave-active {
opacity: 0.01;
transition: opacity 300ms ease-in;
}
你会注意到动画持续时间需要被同时在CSS和渲染方法里被指定;这告诉React什么时候从元素中移除动画类,并且 -- 如果它正在离开 -- 何时从DOM移除元素。
让初始化挂载动画
ReactCSSTransitionGroup
提供了可选的prop transitionAppear
,来为在组件初始挂载添加一个额外的过渡阶段。 通常在初始化挂载时没有过渡阶段因为transitionAppear
的默认值为false
。下面是一个传递transitionAppear
为值true
的例子。
render: function() {
return (
<ReactCSSTransitionGroup transitionName="example" transitionAppear={true} transitionAppearTimeout={500}>
<h1>Fading at Initial Mount</h1>
</ReactCSSTransitionGroup>
);
}
在初始化挂载时 ReactCSSTransitionGroup
将获得example-appear
CSS类 并且example-appear-active
CSS 类在下一刻被添加。
.example-appear {
opacity: 0.01;
}
.example-appear.example-appear-active {
opacity: 1;
transition: opacity .5s ease-in;
}
在初始化挂载,所有的 ReactCSSTransitionGroup
子级将会 appear
但不 enter
。然而,所有后来添加到已存在的 ReactCSSTransitionGroup
的子级将 enter
但不 appear
。
注意:
prop
transitionAppear
在版本0.13
被添加到ReactCSSTransitionGroup
。为了保持向后兼容,默认值被设置为false
。
制定类
可以为你的每一步过渡使用制定类名字。代理传递一个字符串到transitionName,你可以传递一个含有enter
或者leave
类名的对象,或者一个含有 enter
, enter-active
, leave-active
, 和 leave
类名的对象。只要提供了enter 和 leave 的类,enter-active 和 leave-active 类会被决定为后缀'-active' 到类名的尾部。这里是两个使用制定类的例子:
...
<ReactCSSTransitionGroup
transitionName={ {
enter: 'enter',
enterActive: 'enterActive',
leave: 'leave',
leaveActive: 'leaveActive',
appear: 'appear',
appearActive: 'appearActive'
} }>
{item}
</ReactCSSTransitionGroup>
<ReactCSSTransitionGroup
transitionName={ {
enter: 'enter',
leave: 'leave',
appear: 'appear'
} }>
{item2}
</ReactCSSTransitionGroup>
...
动画组必须挂载才工作
为了使过渡效果应用到子级上,ReactCSSTransitionGroup
必须已经挂载到了DOM或者 prop transitionAppear
必须被设置为 true
。下面的例子不会工作,因为 ReactCSSTransitionGroup
随同新项目被挂载,而不是新项目在它内部被挂载。将这与上面的入门指南部分比较一下,看看不同。
render: function() {
var items = this.state.items.map(function(item, i) {
return (
<div key={item} onClick={this.handleRemove.bind(this, i)}>
<ReactCSSTransitionGroup transitionName="example">
{item}
</ReactCSSTransitionGroup>
</div>
);
}, this);
return (
<div>
<button onClick={this.handleAdd}>Add Item</button>
{items}
</div>
);
}
动画一个或者零个项目 Animating One or Zero Items
在上面的例子中,我们渲染了一系列的项目到ReactCSSTransitionGroup
里。然而 ReactCSSTransitionGroup
的子级同样可以是一个或零个项目。这使它能够动画化单个元素的进入和离开。同样,你可以动画化一个新的元素替换当前元素。例如,我们可以像这样实现一个简单的图片轮播器:
var ReactCSSTransitionGroup = require('react-addons-css-transition-group');
var ImageCarousel = React.createClass({
propTypes: {
imageSrc: React.PropTypes.string.isRequired
},
render: function() {
return (
<div>
<ReactCSSTransitionGroup transitionName="carousel" transitionEnterTimeout={300} transitionLeaveTimeout={300}>
<img src={this.props.imageSrc} key={this.props.imageSrc} />
</ReactCSSTransitionGroup>
</div>
);
}
});
禁用动画
如果你想,你可以禁用 enter
或者 leave
动画。例如,有时你可能想要一个 enter
动画,不要 leave
动画,但是 ReactCSSTransitionGroup
会在移除你的DOM节点之前等待一个动画完成。你可以添加transitionEnter={false}
或者 transitionLeave={false}
props 到 ReactCSSTransitionGroup
来禁用这些动画。
注意:
当使用
ReactCSSTransitionGroup
时,没有办法通知你的组件何时过渡效果结束或者在动画时执行任何复杂的逻辑运算。如果你想要更多细粒度的控制,你可以使用底层的ReactTransitionGroup
API,它提供了你自定义过渡效果所需要的挂钩。
底层 API: ReactTransitionGroup
ReactTransitionGroup
是动画的基础。它通过 require('react-addons-transition-group')
访问。当子级被声明式的从其中添加或移除(就像上面的例子)时,特殊的生命周期挂钩会在它们上面被调用。
componentWillAppear(callback)
对于被初始化挂载到 TransitionGroup
的组件,它和 componentDidMount()
在相同时间被调用 。它将会阻塞其它动画发生,直到callback
被调用。它只会在 TransitionGroup
初始化渲染时被调用。
componentDidAppear()
在 传给componentWillAppear
的 回调
函数被调用后调用。
componentWillEnter(callback)
对于被添加到已存在的 TransitionGroup
的组件,它和 componentDidMount()
在相同时间被调用 。它将会阻塞其它动画发生,直到callback
被调用。它不会在 TransitionGroup
初始化渲染时被调用。
componentDidEnter()
在传给 componentWillEnter
的回调
函数被调用之后调用。
componentWillLeave(callback)
在子级从 ReactTransitionGroup
中移除时调用。虽然子级被移除了,ReactTransitionGroup
将会保持它在DOM中,直到callback
被调用。
componentDidLeave()
在willLeave
callback
被调用的时候调用(与 componentWillUnmount
同一时间)。
渲染一个不同的组件
默认情况下 ReactTransitionGroup
渲染为一个 span
。你可以通过提供一个 component
prop 来改变这种行为。例如,下面是你将如何渲染一个<ul>
:
<ReactTransitionGroup component="ul">
...
</ReactTransitionGroup>
每一个React能渲染的DOM组件都是可用的。然而,组件
不需要是一个DOM组件。它可以是任何你想要的React组件;甚至是你自己已经写好的!只要写 component={List}
你的组件会收到 this.props.children
任何额外的、用户定义的属性将会成为已渲染的组件的属性。例如,以下是你将如何渲染一个带有css类的 <ul>
:
<ReactTransitionGroup component="ul" className="animated-list">
...
</ReactTransitionGroup>