我正在研究一個無限滑塊,但我遇到了一個關于 DOM 排序的奇怪錯誤。
在每次影片迭代結束時,最后一個子元素應該被添加到 div.slider-track 元素之前,因此它在滑塊的開頭呈現并在下一次迭代之前向上推其他卡片。它按預期作業,直到第11次迭代,其中卡1被前置連續兩次迭代。Card1 兩次被選為 lastChild 屬性。不應該在第二次第 11 次迭代中選擇 Card10 嗎?是什么賦予了?
const sliderTrack = document.querySelector(".slider-track")
const newCard = (count) => {
const card = document.createElement("div");
card.className = "card";
const label = document.createElement("span")
label.innerText = `Card ${count}`
label.className = "label";
card.append(label)
return card
}
const populateCards = (element) => {
for (let i = 1; i <= 10; i ) {
element.append(newCard(i))
}
}
sliderTrack.addEventListener('animationiteration', () => {
sliderTrack.prepend(sliderTrack.lastChild);
});
populateCards(sliderTrack)
body {
background: #f06d06;
font-family: 'Roboto', sans-serif;
font-weight: bold;
padding: 0;
}
.slider {
overflow: hidden;
}
@keyframes slider {
to {
transform: translate(10%);
}
}
.slider-track {
display: flex;
animation: slider 1s linear;
animation-iteration-count: infinite;
}
.card {
background: white;
width: 10vw;
height: 10vw;
border-radius: 8px;
box-shadow: 2px 2px rgba(0, 0, 0, 20%);
display: flex;
justify-content: center;
align-items: center;
}
<div class="slider">
<div class="slider-track">
</div>
</div>
uj5u.com熱心網友回復:
您的問題是由 DOM 的一個稍微微妙且經常令人討厭的方面引起的。這就是“文本節點”——即作為 HTML 一部分的任何純文本——也算作節點,因此也算作其父元素的子元素。
在這種情況下,因為滑塊軌道的 HTML 是跨 2 行單獨撰寫的:
<div class="slider-track">
</div>
然后,不管你信不信,你實際上有一個換行符,字串"\n"- 作為滑塊軌道元素的子音符之一。
所以當你在初始化時用 Card 1 填充它到 Card 10,你實際上有 11 個孩子,首先是那個文本節點。在您的影片迭代 10 次之后,它以該文本節點作為最后一個元素結束。
到那時,sliderTrack.prepend(sliderTrack.lastChild)只需將那個無辜的換行文本節點從滑塊軌道的 DOM 子節點的末尾移動到前面。這沒有明顯的影響 - 但因為這是在需要 1 秒的影片之后發生的,這意味著在那個特定的“滴答聲”上,似乎沒有發生任何事情,這就是你觀察到的奇怪和不需要的行為。
幸運的是,修復很簡單,當您意識到這是問題所在時。您當然可以簡單地洗掉換行文本,方法是將結束標簽與開始標簽放在同一行上,之間甚至沒有任何空格:
const sliderTrack = document.querySelector(".slider-track")
const newCard = (count) => {
const card = document.createElement("div");
card.className = "card";
const label = document.createElement("span")
label.innerText = `Card ${count}`
label.className = "label";
card.append(label)
return card
}
const populateCards = (element) => {
for (let i = 1; i <= 10; i ) {
element.append(newCard(i))
}
}
sliderTrack.addEventListener('animationiteration', () => {
sliderTrack.prepend(sliderTrack.lastChild);
});
populateCards(sliderTrack)
body {
background: #f06d06;
font-family: 'Roboto', sans-serif;
font-weight: bold;
padding: 0;
}
.slider {
overflow: hidden;
}
@keyframes slider {
to {
transform: translate(10%);
}
}
.slider-track {
display: flex;
animation: slider 1s linear;
animation-iteration-count: infinite;
}
.card {
background: white;
width: 10vw;
height: 10vw;
border-radius: 8px;
box-shadow: 2px 2px rgba(0, 0, 0, 20%);
display: flex;
justify-content: center;
align-items: center;
}
<div class="slider">
<div class="slider-track"></div>
</div>
But while that's not too painful here, it could certainly be very annoying in other cases, forcing you to format your HTML in a less-than-readable way.
So there's another solution for situations exactly like this - as well as lastChild, there is also the more specific lastElementChild which specifically ignores text nodes. That will also work perfectly here, and is probably the better solution in general:
const sliderTrack = document.querySelector(".slider-track")
const newCard = (count) => {
const card = document.createElement("div");
card.className = "card";
const label = document.createElement("span")
label.innerText = `Card ${count}`
label.className = "label";
card.append(label)
return card
}
const populateCards = (element) => {
for (let i = 1; i <= 10; i ) {
element.append(newCard(i))
}
}
sliderTrack.addEventListener('animationiteration', () => {
sliderTrack.prepend(sliderTrack.lastElementChild);
});
populateCards(sliderTrack)
body {
background: #f06d06;
font-family: 'Roboto', sans-serif;
font-weight: bold;
padding: 0;
}
.slider {
overflow: hidden;
}
@keyframes slider {
to {
transform: translate(10%);
}
}
.slider-track {
display: flex;
animation: slider 1s linear;
animation-iteration-count: infinite;
}
.card {
background: white;
width: 10vw;
height: 10vw;
border-radius: 8px;
box-shadow: 2px 2px rgba(0, 0, 0, 20%);
display: flex;
justify-content: center;
align-items: center;
}
<div class="slider">
<div class="slider-track">
</div>
</div>
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/359547.html
標籤:javascript html css dom css动画
