React css 转换无法正常工作

IT技术 css reactjs css-transitions
2021-05-13 07:51:50

我写了一个 React 应用程序,使用 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 项目来显示问题。它有这个演示项目的完整代码。

我试图添加日志条目componentDidUpdatecomponentDidMountcomponentWillUnmount方法来显示这些组件是否是重新创建或更新,这表明它们都更新(不重新创建,或删除),每一秒。

4个回答

好吧,在我开始赏金之后,因为我也有这个问题,我终于找到了问题所在。

当您使用绝对位置(或相对位置,如您的情况)时,如果您每次都重新渲染整个列表,React 将重新排列 DOM 中的元素(如您所说,元素不会被重新创建,只是更新)。但这会导致过渡出现问题......显然,如果在过渡运行时移动元素,那么最终会剪切动画。

因此,对于您想要使用绝对位置的情况,关键概念是渲染元素的容器一次(在这种情况下,只是 div)并且仅根据新顺序更改内部内容。如果您需要添加更多元素,只需在最后添加它们。

我修改了你的代码笔,以便它反映我在说什么。我的示例非常愚蠢,因为我刚刚创建了 4 个临时 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>
  );
}

因此,问题基本上在于如何创建容器的静态列表以及如何遍历该列表,以便第一个容器呈现数据的第一个元素,第二个容器呈现第二个元素,等等。

希望它有所帮助,这个问题也让我发疯了!:)

我知道事实并非如此,但因为我来到这里也是为了寻找React css transition does not work correctly,所以我只想分享:

如果您在 内部使用箭头函数创建一个元素render,它不会得到正确的动画效果,因为总是会创建一个新的组件。您应该在外部创建一个函数并在“渲染”中调用它。

你可以使用indexas key来欺骗 React 如果你考虑el,index作为起始位置 (index) 和结束位置 (el),元素在过渡结束时已经移动到旧的结束位置,当它在那里时,它被新的开始位置和(index) 被切换以匹配新的设置。这是因为当您key在 react 中设置元素时,虚拟 DOM 将始终将其解释为相同的元素。为此,您通常将 index 设置为“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>

DOM每次都重新创建元素。
您应该定义收集键值。我将您的键值更改'' + el'' + index.

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

只更改css属性:)