React為動畫提供了一個附加組件ReactTransitionGroup,這個附加組件是動畫的底層API,並且還提供了一個附件組件ReactCSSTransitionGroup,ReactCSSTransitionGroup能夠簡單的實現基於css的動畫和轉換
高級API ReactCSSTransitionGroup
ReactCSSTransitionGroup是一個基於ReactTransitionGroup的API,當一個React組件插入或者移除DOM時,它是一種簡單的去執行css轉換和動畫的方法
以一個demo舉例
ReactCSSTransitionGroup是ReactTransitions的接口,可以把它當做一個簡單的元素,它包裹着所有想添加動畫效果的React組件。下面有一個例子:
var ReactCSSTransitionGroup = require('react-addons-css-transition-group'); var React = require('react'); var ReactDOM = require('react-dom'); var data = ['one','two','three']; var Control = React.createClass({ getInitialState:function(){ return { 'items':this.props.data } }, addItem:function(){ var newItems = this.state.items.concat('four'); this.setState({ 'items':newItems }); }, removeItem:function(i){ var newItems = this.state.items; newItems.splice(i,1); this.setState({ 'items':newItems }); }, render:function(){ var $this = this; var List = this.state.items.map(function(value,index){ return <div key={value} onClick = {$this.removeItem.bind($this,index)}> { value}</div> }); return ( <div> <button onClick={this.addItem}>add Item</button> <ReactCSSTransitionGroup transitionName='example' transitionEnterTimeout={500} transitionLeaveTimeout={300}> {List} </ReactCSSTransitionGroup> </div> ) } }); ReactDOM.render(<Control data={data}/> ,document.getElementById('content'));
對例子的解釋:
(1)你需要用npm安裝react-addons-css-transition-group,然后通過require在文件中引入,然后賦給一個變量,在這里將這個變量命名為ReactCSSTransitionGroup,也可以不取別的名字
(2)為每一個ReactCSSTransitionGroup組件的子元素設置一個key屬性,就算它只有一個子元素。key值必須是唯一的。設置一個key屬性是為了讓react確定那個子元素插入了,移除了,或者保持。
(3)在這個demo中,當一個新的子元素被添加到ReactCSSTransitionGroup中,它就會得到一個example-enter CSS類名,隨后它又會得到一個example-enter-active CSS類名。這些類名基於transitionName屬性值。你能夠使用這個類名去實現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; }
這些樣式中transition-duration值必須與ReactCSSTransitionGroup組件的transitionEnterTimeout和transitionLeaveTimeout屬性值一一對應
(4)這個時候你點擊'add Item'按鈕將會以一種淡入的方式添加一個新的子元素,點擊一個已經存在的子元素,這個被點擊的子元素將會以一種淡出的方式被移除。
Animate Initial Mounting
ReactCSSTransitionGroup提供了一個可選的屬性transitionAppear,如果將這個屬性設置為true,在組件的初始化裝置就會添加一個額外的轉換階段。默認情況下transitionAppear為false,如下:
render: function() { return ( <ReactCSSTransitionGroup transitionName="example" transitionAppear={true} transitionAppearTimeout={500}> {list} </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的裝載階段就會有一個淡入的動畫。在初始化裝載階段,每一個ReactCSSTransitionGroup子元素都是appear而不是enter,然而,子元素進入一個已經存在的ReactCSSTransitionGroup,這個子元素是enter而不是appear
自定義類名
在上面的demo中,我們給transitionName屬性設置了一個字符串example,所以,每一個階段涉及的CSS類名都是以example開頭的。我們也可以給transitionName設置一個字符串,這樣可以為每一個階段自定義類名,如下有兩種設置方式:
<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>
Animation Group Must Be Mounted To Work
為了讓每一個子元素都有一個淡入和淡出的效果,子元素必須進入或離開一個已經被裝載的ReactCSSTransitionGroup組件中,或者ReactCSSTransitionGroup的transitionAppear屬性為true,下面這個例子就不會有淡入和淡出的效果,因為,ReactCSSTransitionGroup和一個新的子元素被單獨裝載,而不是子元素載入一個已經存在的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> ); }
一個或者0個子元素
在上面的例子中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> ); } });
禁用動畫
如果你願意,你能夠禁用leave或者enter動畫。例如,你想讓子元素有一個enter動畫而沒有一個leave動畫,但是在默認情況下,在你移除DOM節點之前,ReactCSSTransitionGroup會等待一個動畫去完成。你能給ReactCSSTransitionGroup設置transitionEnter={false} 或者 transitionLeave={false}去禁用這些動畫