Reactjs 如何在使用贴图渲染的状态或道具中移动项目时添加转换

Reactjs 如何在使用贴图渲染的状态或道具中移动项目时添加转换,reactjs,css-transitions,transition,Reactjs,Css Transitions,Transition,假设我正在使用.map函数从一个状态的道具呈现一个列表 我想更改列表的顺序;所以我改变了我的状态或道具的顺序。相应地反映了变化,但我如何在这种情况下添加平滑过渡,以便用户感觉他/她做了什么。否则,用户体验会降低 他是我想要实现的基本想法 import React from "react"; import ReactDOM from "react-dom"; import "./styles.css"; export class App extends React.Component {

假设我正在使用.map函数从一个状态的道具呈现一个列表

我想更改列表的顺序;所以我改变了我的状态或道具的顺序。相应地反映了变化,但我如何在这种情况下添加平滑过渡,以便用户感觉他/她做了什么。否则,用户体验会降低

他是我想要实现的基本想法

import React from "react";
import ReactDOM from "react-dom";

import "./styles.css";

export class App extends React.Component {
  constructor() {
    super();
    this.state = {
      items: [
        { key: 0, name: "Hello" },
        { key: 0, name: "Sello" }, // move this down with transition
        { key: 0, name: "Wello" }, // move this up with transition
        { key: 0, name: "Zello" },
        { key: 0, name: "Pello" },
        { key: 0, name: "Aello" }
      ]
    };
  }
  reShuffle = () => {
    this.setState({
      items: this.state.items.map((item, index) => {
        if (index === 1) {
          return this.state.items[2];
        }
        if (index === 2) {
          return this.state.items[1];
        }
        return item;
      })
    });
  };
  render() {
    return (
      <div className="App" style={{ transition: "all 0.5s ease" }}>
        <button onClick={this.reShuffle}> Click Me </button>
        {this.state.items.map(item => <li key={item.key}> {item.name} </li>)}
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
从这里很容易复制

在react元素上执行css转换时,您需要处理一个附加状态:转换本身

因此,首先更改组件的状态,以便css转换将更改它们,然后更改转换结束时的状态,使react与转换结束时组件的样式匹配

在您的情况下,当您单击切换元素时,您必须计算css更改,该更改将具有与切换元素相同的效果,然后当转换结束时,您实际切换元素

我们需要为项目添加一个top属性和一个适当的键:

constructor() {
super();
this.state = {
  items: [
    { key: 0, name: "Hello", top: 0 },
    { key: 1, name: "Sello", top: 0 }, // move this down
    { key: 2, name: "Wello", top: 0 }, // move this up
    { key: 3, name: "Zello", top: 0 },
    { key: 4, name: "Pello", top: 0 },
    { key: 5, name: "Aello", top: 0 }
  ],
  transitioning: {}
};
this.itemTransitionCount = 0;
}

请注意稍后的itemTransitionCount

首先将元素包装在元素中,并将引用附加到:

此代码将启动要在li items=>上设置的顶部过渡,切换动画将在下一次渲染期间发生

我们用onTransitionEnd处理程序捕获两个动画的结尾,并检查evt.target!==evt.currentTarget之所以存在是因为转换事件冒泡,计数之所以存在是因为两个元素都将引发事件,但我们希望在两个转换结束时都执行一次操作:

itemTransitionEnd = evt => {
if (evt.target !== evt.currentTarget) return;
// alert("transitionEnd");
this.itemTransitionCount++;
if (this.itemTransitionCount < 2) return;
this.itemTransitionCount = 0;
this.setState({
  items: this.state.items.map((item, index) => {
    if (index === 1) {
      return { ...this.state.items[2], top: 0 };
    }
    if (index === 2) {
      return { ...this.state.items[1], top: 0 };
    }
    return item;
  })
});
})

上面的代码实际上在转换结束时切换元素并重置其相对顶部。对于下一个转换,转换计数也会重置

这演示了React中css过渡动画的两步渲染


明亮的过渡的开始和结束都很好!你应该把它作为一个中等职位或东西。我为此绞尽脑汁。
reShuffle = () => {
this.setState({
  items: this.state.items.map((item, index) => {
    if (index === 1) {
      const top2 = this.ulDom.children[2].offsetTop;
      const top1 = this.ulDom.children[1].offsetTop;
      const top = top2 - top1;
      return { ...this.state.items[1], top };
    }
    if (index === 2) {
      const top1 = this.ulDom.children[1].offsetTop;
      const top2 = this.ulDom.children[2].offsetTop;
      const top = top1 - top2;
      return { ...this.state.items[2], top };
    }
    return item;
  })
});
itemTransitionEnd = evt => {
if (evt.target !== evt.currentTarget) return;
// alert("transitionEnd");
this.itemTransitionCount++;
if (this.itemTransitionCount < 2) return;
this.itemTransitionCount = 0;
this.setState({
  items: this.state.items.map((item, index) => {
    if (index === 1) {
      return { ...this.state.items[2], top: 0 };
    }
    if (index === 2) {
      return { ...this.state.items[1], top: 0 };
    }
    return item;
  })
});