React css转换无法正常工作

时间:2017-08-14 09:12:11

标签: css3 reactjs css-transitions

我使用CSS过渡编写了一个React应用程序。但是这些转换在某些组件中无法正常工作。在my app中,只有向上移动的组件才能正常运行,向下移动的组件会在没有动画的情况下立即移动。 (我希望它们都带动画。)

这是我在那里使用的CSS:

componentDidUpdate

更新:

我还构建了一个codepen.io project来显示问题。它有完整的演示项目代码。

我尝试向componentDidMountcomponentWillUnmountmy $qstr = "select $subject.id as id, $subject.status as status, $subject.title as title, $subject.component as component, $subject.submitted_date as submitted_date, $subject.closed_date as closed_date from $subject where ($subject.title = 'PM_Production' and ($subject.status = 'complete' OR $subject.status = 'rejected'))"; 方法添加日志条目,以显示是否重新创建或更新了这些组件,它表明它们都已更新(不是每次重新创建或删除)。

5 个答案:

答案 0 :(得分:19)

好吧,在我开始赏金之后因为我也遇到了这个问题,我终于找到了什么似乎是问题。

当你使用绝对位置(或相对的,如你的情况)时,如果你每次重新渲染整个列表,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 :(得分:2)

如果要从虚拟DOM中删除元素,则react会更新其内容,因此您将看不到动画。您可以做的是使用react-transition-group或者告诉您的应用在调用事件后更新dom之前等待x ms或使用可见性在隐藏和显示之间切换,而不是从DOM中完全删除它。

答案 2 :(得分:2)

您可以使用index作为密钥欺骗React。如果您将elindex视为起始位置(索引)和结束位置(el),则该元素在转换结束时已移至旧的结束位置,并且当它在那里时,它被新的起始位置接管,并且(索引)被切换以匹配新的设置。这是因为当您在react中的元素中设置key时,虚拟DOM将始终将其解释为同一元素。并且为了它,你通常将索引设置为“id”。

我只通过切换index / 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>

答案 3 :(得分:2)

我知道不是这种情况,但是由于我到这里也是在寻找React css transition does not work correctly,所以我只想分享一下:

如果您使用render 中的箭头功能创建一个元素,则该元素将无法正确显示动画,因为始终会创建一个新的组件。 您应该在外部创建一个函数,然后在“渲染”中调用它。

答案 4 :(得分:1)

您每次都重新创建DOM个元素 您应该定义collect键值。 我将键值'' + el更改为'' + index

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

只需更改css属性:)