2017-08-14 70 views
14

我寫了一個React應用程序,使用CSS轉換。但是這些轉換在某些組件中無法正常工作。在my app中,只有向上移動的組件運行良好,向下移動的組件沒有動畫即時移動。 (我想他們兩個動畫移動)反應CSS轉換不能正常工作

這裏是我以前在那裏的CSS:

div.canvas { 
    position: absolute; 
    top: 90px; 
    left: 60px; 
    width: 640px; 
    height: 480px; 
    border: 1px solid #999; 
    background: white; 

} 

div.canvas-rect { 
    position: relative; 
    margin-left: 20px; 
    margin-top: 10px; 
    height: 20px; 
    background: green; 

    transition: all 1s linear; 
    -moz-transition: all 1s linear; /* Firefox 4 */ 
    -webkit-transition: all 1s linear; /* Safari 和 Chrome */ 
    -o-transition: all 1s linear; /* Opera */ 

} 

更新:

我還內置了codepen.io project顯示的問題。它有這個演示項目的完整代碼。

我試圖日誌條目添加到componentDidUpdatecomponentDidMountcomponentWillUnmount方法來顯示是否這些組件是重新創建或更新,這表明它們都更新(不重新創建,或刪除)每秒。

+0

我們不能調試僅2 CSS規則,你必須張貼工作代碼片段重現問題 – LGSon

+0

@LGSon對不起,我已經建立了一個codepen.io項目將盡快更新問題。 – cmal

+0

通過簡單地交換一些頂部值,它們也開始向下生成動畫。我想你需要檢查這些值如何切換項目。 https://codepen.io/anon/pen/ZJazQa ...還要注意,未加前綴的屬性應該總是在CSS – LGSon

回答

11

那麼,在我開始賞金之後,因爲我也有這個問題,我終於找到了什麼似乎是問題所在。

當你使用絕對位置(或者相對,如你的情況),如果你每次重新渲染整個列表,React會重新排列DOM中的元素(正如你所說的,元素不是正在重新創建,只是更新)。但是這會產生轉換問題......顯然,如果在轉換運行時移動元素,則最終會切割動畫。

因此,對於您想要使用絕對位置的情況,關鍵概念是渲染元素的容器一次(在這種情況下,只是div),並且只根據新的順序更改內部內容。如果您需要添加更多元素,請在最後添加它們。

我修改了你的codepen,以便它反映我正在說的內容。我的例子非常愚蠢,因爲我剛剛創建了4個ad-hoc div,但它說明了這個想法:根據需要創建儘可能多的容器,但不要使用每次都重新創建它們的地圖,否則會切換您的過渡。

https://codepen.io/damianmr/pen/boEmmy?editors=0110

const ArrList = ({ 
    arr 
}) => { 
    return (
    <div style={{position: 'relative'}}> 
     <div className={`element element-${arr[0]} index-${arr[0]}`}>{arr[0]}</div> 
     <div className={`element element-${arr[1]} index-${arr[1]}`}>{arr[1]}</div> 
     <div className={`element element-${arr[2]} index-${arr[2]}`}>{arr[2]}</div> 
     <div className={`element element-${arr[3]} index-${arr[3]}`}>{arr[3]}</div> 
    </div> 
); 
} 

所以,這個問題基本上是你如何創建容器的靜態列表,你通過這個列表如何迭代,從而第一容器呈現數據的第一要素,第二個容器中第二元素等

希望它有幫助,這個問題也讓我瘋了! :)

+1

我希望我能把這個答案投票上千次......謝謝! – MarkoCen

+0

歡迎您! @MarkoCen – damianmr

1

如果您從虛擬DOM中移除元素,則反應會更新其內容,因此您將看不到動畫。你可以做的是使用react-transition-group或者告訴你的應用在更新dom之前等待x毫秒,一旦事件被調用,或者使用可見性在隱藏和顯示之間切換,而不是從DOM完全刪除它。

+0

前綴後面謝謝。但是元素還沒有從V-DOM中刪除,只是更新了組件。我已經更新了這個問題。 – cmal

1

您每次都重新創建了DOM個元素。
您應該定義收集鍵值。 我將您的密鑰值'' + el更改爲'' + index

<div key={'' + index} className={'element element-' + el + ' index-' + index} > 

只要改變css性能只:)

1

你就可以欺騙使用index關鍵反應。如果您考慮elindex作爲起始位置(索引)和結束位置(el),則該元素在轉換結束時已移至舊結束位置,並且在其位於該位置時由新的起始點接管位置和(索引)被切換以匹配新的設置。這是因爲當您將key設置爲反應中的元素時,虛擬DOM將始終將其解釋爲它是相同的元素。爲了這個原因,你一般將索引設置爲「id」。

我只是通過切換索引/ el(以及將元素位置設置爲絕對)做了一個工作示例。

const {combineReducers, createStore} = Redux; 
 
const { Provider, connect } = ReactRedux; 
 

 
const ArrList = ({ 
 
    arr 
 
}) => (
 
    <div>{ 
 
    arr.map((el, index)=> 
 
      <div 
 
      key={""+index} 
 
      className={`element element-${el}` + ` index-${el}`} 
 
      > 
 
      {el} 
 
      </div>) } 
 
    </div> 
 
) 
 
     
 
const mapStateToArrList = (state) => { 
 
    return { 
 
    arr: state.appReducer.arr 
 
    } 
 
}; 
 

 
const App = connect(mapStateToArrList, null)(ArrList); 
 

 
const initialState = { 
 
    arr: [1, 2, 3, 4] 
 
} 
 

 
const appReducer = (state = initialState, action) => { 
 
    switch(action.type) { 
 
    case "tick": 
 
     return { 
 
     ...state, 
 
     arr: _.shuffle(state.arr) 
 
     } 
 
    default: 
 
     return state 
 
    } 
 
} 
 

 
const reducer = combineReducers({ 
 
    appReducer 
 
}) 
 

 

 
const store = createStore(reducer) 
 

 
ReactDOM.render(
 
    <Provider store={store}> 
 
    <App /> 
 
    </Provider>, 
 
    document.getElementById('root') 
 
) 
 

 
const dispatcher =() => { 
 
    store.dispatch({ 
 
    type: "tick" 
 
    }) 
 
    setTimeout(dispatcher, 1000) 
 
} 
 

 
dispatcher()
.element { 
 
    position: absolute; 
 
    height: 20px; 
 
    background: green; 
 
    margin-left: 20px; 
 
    margin-top: 20px; 
 

 
    text-align: right; 
 
    color: white; 
 
    line-height: 20px; 
 

 
    transition: all 1s ease-in; 
 
    -moz-transition: all 1s ease-in; /* Firefox 4 */ 
 
    -webkit-transition: all 1s ease-in; /* Safari 和 Chrome */ 
 
    -o-transition: all 1s ease-in; /* Opera */ 
 

 
} 
 

 
.element-1 { 
 
    width: 20px; 
 
} 
 

 
.element-2 { 
 
    width: 40px; 
 
} 
 

 
.element-3 { 
 
    width: 60px; 
 
} 
 

 
.element-4 { 
 
    width: 80px; 
 
} 
 

 
.index-1 { 
 
    top: 20px; 
 
} 
 

 
.index-2 { 
 
    top: 40px; 
 
} 
 

 
.index-3 { 
 
    top: 60px; 
 
} 
 

 
.index-4 { 
 
    top: 80px; 
 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/3.7.2/redux.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/5.0.6/react-redux.js"></script> 
 

 
<div id="root"></div>