gpt4 book ai didi

javascript - 通过更新 react CSS 过渡不一致

转载 作者:行者123 更新时间:2023-12-01 16:25:45 25 4
gpt4 key购买 nike

下面的代码片段有四个框。目的是这些盒子顺序将被打乱,并在它们进入新位置时出现过渡动画。每个框的键对应于 useState 中源数组中的一个颜色值。每次通过 shuffle 按钮更新时,源数组的值都会被打乱。然后我通过返回函数中的数组进行映射。我为每个盒子设置了 2 个类名。一个类名与索引对应,用于定位。另一个类名与源数组值相对应,并且始终与该框的键一致。

我的问题是 react 似乎随机决定要注意和协调哪些键,以及忽略哪些键并重新安装这些元素。您可以在这里看到,一些元素正确过渡,而另一些元素只是跳转到它们的目标位置。我不知道为什么会发生这种情况。有人可以帮忙吗?

编辑:我不认为这是关于不需要的重新安装的协调问题。 React 正确地尊重 key ,而不是重新安装任何 key 。所以问题在于 React 如何处理在更新期间添加的 CSS 转换类。有些过渡有效,有些则无效。这可能只是引擎的限制,但如果有人有任何进一步的煽动,请分享。

const {useState} = React;

function App() {
const [state, setState] = useState(['Red', 'Green', 'Blue', 'Black'])

function handleShuffle() {
const newState = _.shuffle(state)
setState(newState)
}

return (
<div className="App">
{state.map((sourceValue, index) => {
return (
<div className={
'box positionAt' + index + ' sourceValue' + sourceValue
}
key={sourceValue} ></div>
)
})}

<button id="shuffle" onClick={handleShuffle}> shuffle < /button>
</div>
);
}

const rootElement = document.getElementById("root");
ReactDOM.render( <
App / > ,
rootElement
);
.App {
position: relative;
width: 200px;
height: 200px;
background-color: gray;
}

.box {
width: 25px;
height: 25px;
position: absolute;
transition: transform 1s;
}

.positionAt0 {
transform: translate(0px, 0px);
}

.positionAt1 {
transform: translate(175px, 0px);
}

.positionAt2 {
transform: translate(0px, 175px);
}

.positionAt3 {
transform: translate(175px, 175px);
}

.sourceValueGreen {
background-color: green;
}

.sourceValueBlue {
background-color: blue;
}

.sourceValueRed {
background-color: red;
}

.sourceValueBlack {
background-color: black;
}

#shuffle {
position: absolute;
top: 0px;
left: 75px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>
<div id="root"></div>

最佳答案

我花了一段时间才弄清楚,因为为盒子设置正确的键似乎是正确的事情。

我使用开发工具验证了 key s 工作,通过检查一个盒子并将其存储在一个变量(b = $0)中,改组,重新检查具有相同 key 的盒子(颜色)并将其与存储的节点( $0 === b 进行比较,为 true )。所以每个键的 DOM 节点都是稳定的。

但这对于 CSS 过渡还不够,因为浏览器正在改变 DOM 中元素的顺序。

你可以在一个最小化的例子中看到它,用于有效地重新排序 DOM 中的元素(我假设 React 在必须重新排序元素时在内部做类似的事情):

function reorder() {
const list = document.querySelector("ul");
list.appendChild(list.firstElementChild);
}
 <ul>
<li>List-item #1</li>
<li>List-item #2</li>
</ul>
<button onclick="reorder()">reorder!</button>


运行示例并在结果 <ul> 上设置 DOM 断点“子树修改”的 DOM 节点,见截图。

enter image description here

如果您单击“重新排序!”,浏览器会在删除 <li> 时首先中断。 .如果您继续,并且在继续后立即(Firefox: <F8>),浏览器会再次中断并插入 <li> .

(在我的测试中,Chrome 提供的关于中断的信息有点误导,Firefox 更擅长于此)

因此,浏览器在技术上将重新排序实现为“删除和插入”,这会破坏 CSS 过渡。

有了这些知识,就可以通过在 DOM 中固定框的顺序来轻松修复代码(不需要更改 DOM 中的顺序,因为位置只能通过类设置):

(注:*HTML 和 CSS 不变,JavaScript 中的更改用 NEW 或 CHANGE * 标记)

const {useState} = React;

// NEW: List of boxes for a stable order when rendering to the DOM:
const boxes = ['Red', 'Green', 'Blue', 'Black'];

function App() {
const [state, setState] = useState(boxes); // CHANGE: reuse boxes here

function handleShuffle() {
const newState = _.shuffle(state)
setState(newState)
}

return (
<div className="App">
{/* CHANGE: loop over boxes, not state and lookup position, which is used for the positionAt... class */
boxes.map((sourceValue, index) => {
const position = state.indexOf(sourceValue);
return (
<div className={
'box positionAt' + position + ' sourceValue' + sourceValue
}
key={sourceValue} ></div>
)
})}

<button id="shuffle" onClick={handleShuffle}> shuffle < /button>
</div>
);
}

const rootElement = document.getElementById("root");
ReactDOM.render( <
App / > ,
rootElement
);
.App {
position: relative;
width: 200px;
height: 200px;
background-color: gray;
}

.box {
width: 25px;
height: 25px;
position: absolute;
transition: transform 1s;
}

.positionAt0 {
transform: translate(0px, 0px);
}

.positionAt1 {
transform: translate(175px, 0px);
}

.positionAt2 {
transform: translate(0px, 175px);
}

.positionAt3 {
transform: translate(175px, 175px);
}

.sourceValueGreen {
background-color: green;
}

.sourceValueBlue {
background-color: blue;
}

.sourceValueRed {
background-color: red;
}

.sourceValueBlack {
background-color: black;
}

#shuffle {
position: absolute;
top: 0px;
left: 75px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>
<div id="root"></div>


注意:现在即使没有 key 也可以使用已设置。

关于javascript - 通过更新 react CSS 过渡不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61960411/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com