2017-08-14 66 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>