react之CSS动画效果

React干货 admin 暂无评论

TransitionGroup和CSSTransitionGroup已移动到react-transition-group有社区维护。它的1.x分支与现有插件的API是完全兼容的。

TransitionGroup是一个具有低级API的动画组件,而CSSTransitionGroup是一个基于css的animation和transition更容易被使用的组件。

高级API:CSSTransitionGroup

1.import { CSSTransitionGroup } from 'react-transition-group' // ES6
2.var CSSTransitionGroup = require('react-transition-group/CSSTransitionGroup') // ES5 with npm
3.class TodoList extends React.Component{
4.    constructor(){
5.        super();
6.
7.        this.state = {
8.            items: [
9.                'hello',
10.                'world',
11.                'click',
12.                'me'
13.            ]
14.        };
15.        this.handleAdd = this.handleAdd.bind(this);
16.    }
17.
18.    handleAdd() {
19.        const newItems = this.state.items.concat([
20.          prompt('Enter some text')
21.        ]);
22.        this.setState({items: newItems});
23.    }
24.
25.    handleRemove(i) {
26.        let newItems = this.state.items.slice();
27.        newItems.splice(i, 1);
28.        this.setState({items: newItems});
29.    }
30.
31.    render(){
32.        const items = this.state.items.map((item, i) => (
33.          <div key={i} onClick={() => this.handleRemove(i)}>
34.            {item}
35.          </div>

36.        ));
37.        return (
38.            <div>
39.                <button type="button" onClick={this.handleAdd}>Add Item</button>
40.                <CSSTransitionGroup
41.                    transitionName="example"
42.                    transitionEnterTimeout={500}
43.                    transitionLeaveTimeout={300}
44.                >

45.                    {items}
46.                </CSSTransitionGroup>
47.            </div>

48.        );
49.    }
50.}

在这个组件中,当一个新的Item被添加时,ReactCSSTransitionGroup将获得一个example-enter的类和example-enter-active的类,这些类名是基于trnasitionName的值。

您可以使用这些类来触发css动画或转换。例如:尝试添加如下样式:

1..example-enter{
2.    opacity: 0.01;
3.}
4..example-enter.example-enter-active{
5.    opacity: 1;
6.    transition: opacity 500ms ease-in;
7.}
8..example-leave{
9.    opacity: 1;
10.}
11..example-leavel.example-leavel-active{
12.    opacity: 0.01;
13.    transition: opacity 300ms ease-in;
14.}

初始化加载动画

ReactCSSTransitionGroup提供一个可选的属性transitionAppear,以在组件的初始渲染时添加额外的过渡阶段。默认为false:

1.render() {
2.  return (
3.    <CSSTransitionGroup
4.      transitionName="example"
5.      transitionAppear={true}
6.      transitionAppearTimeout={500}
7.      transitionEnter={false}
8.      transitionLeave={false}>

9.      <h1>Fading at Initial Mount</h1>
10.    </CSSTransitionGroup>

11.  );
12.}

在初始化渲染ReactCSSTransitionGroup过程中,example-appear类和example-appear-active类将被添加。

1..example-appear {
2.  opacity: 0.01;
3.}
4..example-appear.example-appear-active {
5.  opacity: 1;
6.  transition: opacity .5s ease-in;
7.}

在初始化渲染阶段,所有ReactCSSTransitionGroup的孩子节点将会appear而不是enter,然而,所有孩子稍后被渲染后将会触发enter而不是appear。

注意:

属性transitionAppear在0.13版本中才被添加进入ReactCSSTransitionGroup中,为了向后兼容,默认值为false。

然而,transitionEnter和transtionLeave默认为true,所以你默认只要指定transitionEnterTimeout和transitionLeaveTimeout。

自定义类名

当然,我们也可以使用自定义类名代替每一步默认的类名。你可以通过传递一个包含enter或leave或appear等等的对象给transitionName而不是字符串。

如果未提供active时,默认会为添加-active后的类名:

1.<CSSTransitionGroup
2.    transitionName={
3.        {
4.            enter: 'enter',
5.            enterActive: 'enterActive',
6.            leave: 'leave',
7.            leaveActive: 'leaveActive',
8.            appear: 'appear',
9.            appearActive: 'appearActive'
10.        }
11.    }
12.>
13.{item}
14.</CSSTransitionGroup>
15.<CSSTransitionGroup
16.  transitionName={ {
17.    enter: 'enter',
18.    leave: 'leave',
19.    appear: 'appear'
20.  } }>
21.  {item2}
22.</CSSTransitionGroup>

动画组必须已经被渲染到DOM

为了时其子节点的动画能够生效,ReactCSSTransitionGroup必须已经被加载进DOM中,或者transitionAppear必须为true。

下面的例子将不会正常运行,因为ReactCSSTransitionGroup被和新的item一起渲染,而不是新的item渲染进其子节点:

1.render() {
2.  const items = this.state.items.map((item, i) => (
3.    <div key={item} onClick={() => this.handleRemove(i)}>
4.      <CSSTransitionGroup transitionName="example">
5.        {item}
6.      </CSSTransitionGroup>
7.    </div>

8.  ));
9.  return (
10.    <div>
11.      <button onClick={this.handleAdd}>Add Item</button>
12.      {items}
13.    </div>

14.  );
15.}

渲染一个或零个子节点

在上面的例子中,我们渲染了一个列表节点,当然,ReactCSSTransitionGroup也可以渲染一个或零个节点:

1.import ReactCSSTransitionGroup from 'react-addons-css-transition-group';
2.function ImageCarousel(props) {
3.  return (
4.    <div>
5.      <CSSTransitionGroup
6.        transitionName="carousel"
7.        transitionEnterTimeout={300}
8.        transitionLeaveTimeout={300}>

9.        <img src={props.imageSrc} key={props.imageSrc} />
10.      </CSSTransitionGroup>
11.    </div>
12.  );
13.}

禁用动画

可以通过设置false来禁用指定阶段,如:transitionEnter为false禁用进入后的动画效果。

注意:使用ReactCSSTransitionGroup你没办法知道一个transition已经结束或其他更详细的细节,如果你需要,则得使用低级APIReactTransitionGroup,它提供更多的钩子让你能够监听。

低级API:TransitionGroup

1.import TransitionGroup from 'react-transition-group/TransitionGroup' // ES6
2.var TransitionGroup = require('react-transition-group/TransitionGroup') // ES5 with npm

ReactTransitionGroup是动画的基础。当子节点添加或删除,下面这些钩子函数将会被调用:

  • componentWillAppear(callback)

这个方法将在渲染到节点时调用,它将阻塞其他当前正在发生的动画,知道callback被调用。这个方法仅仅在初始化渲染TransitionGroup时被调用。

  • componentDidAppear()

这个方法将在componentWillAppear的callback被调用后被调用。

  • componentWillEnter(callback)

当有新元素被添加到TransitionGroup时调用,它将会阻塞其他动画知道callback调用。

  • componentDidEnter()

在componentWillEnter的callback调用后触发。

  • componentWillLeave(callback) 
    当有元素被移除时触发,尽管元素已经被删除,但它还是还将保留在DOM中,直到callback被调用。

  • componentDidLeave() 
    在componentWillLeave的callback被调用时触发(和componentWillUnmount()同时触发)。

渲染其他组件

TransitionGroup默认渲染为一个span,你通过增加一个compoennt属性改变默认行为:

1.<TransitionGroup component="ul">
2.    
{/*...*/}
3.</TranstionGroup>

另外,用户自定义的属性也会对应增加到组件的属性,如下例子,ul也将会得到className属性:

1.<TransitionGroup component="ul" className="animated-list">
2.  
{/* ... */}
3.</TransitionGroup>

所有react可以渲染的组件都可以成为component,它不是必须为一个DOM节点,如:component={CustomList},那么,TransitionGroup的子节点传递给CustomList组件的属性this.props.children。

渲染单独的子节点

我们经常会用TransitionGroup来作为单独子节点的渲染和移除时的效果,诸如手风琴效果的面板。

正常情况下,TransitionGroup把其子节点包裹在一个span(或者自定义的component中),这是因为react的render函数必须返回单独子节点,但是TransitionGroup并不需要这样的规则。

然而,如果你需要只渲染一个单独子节点,你可以通过定义一个只渲染第一个子节点的组件:

1.function FirstChild(props) {
2.  const childrenArray = React.Children.toArray(props.children);
3.  return childrenArray[0] || null;
4.}

现在你可以指定TransitionGroup的component属性为FirstChild来避免包裹外层组件:

1.<TransitionGroup component={FirstChild}>
2.  {someCondition ? <MyComponent /> : null}
3.</TransitionGroup>

这仅仅在你只想要渲染一个子节点时有用,在需要渲染多个节点时没有效果。


转载请注明:React教程中文网 - 打造国内领先的react学习网站-react教程,react学习,react培训,react开 » react之CSS动画效果

喜欢 ()or分享