如何在移动状态中的项目或使用地图渲染的道具时添加过渡



>假设我正在使用.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);

可从此处轻松复制 https://codesandbox.io/s/648z61kvrn

在 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>元素包装在<ul>元素中,并将 ref 附加到<ul>

ulLoad = c => (this.ulDom = c);
render() {
...
<ul
ref={this.ulLoad}
style={{ position: "relative", display: "inline-block" }}
>
{
this.state.items.map(item => (
<li
key={item.key}
onTransitionEnd={this.itemTransitionEnd}
style={{
transition: item.top ? "top 0.5s ease" : "none",
position: "relative",
top: item.top
}}
>
{item.name}
</li>
))
}
</ul>
....
}

这将允许计算子<li>的相对位置

然后以这种方式更改您的 reShuffle 处理程序:

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;
})
});

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

我们使用 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 过渡动画的两步渲染。

在这里工作沙盒

最新更新