#javascript
#javascript
Вопрос:
У меня есть три div, каждый из которых содержит еще один div, которые скрыты классом с именем none . когда я нажимаю кнопку show squares , функция displaySquares должна удалить все классы none, но это не так. lOb.classList возвращает undefined на определенной итерации, и я не знаю почему? Любая помощь будет оценена.
function displaySquares(x){
var dr = document.getElementsByClassName(x),pl=dr.length,i=0;
for (i; i < pl; i ) {
var lOb = dr[i];
if (lOb.classList) {
if (lOb.classList.contains(x)) {
lOb.classList.remove(x);
}
} else { //fallback for classList
var r = new RegExp("\b" x "\b", "g");
if (r.test(lOb.className)) {
lOb.className = lOb.className.replace(r, "");
}
}
}
}
.clcn{
width:130px;
height:130px;
background: rgba(0,0,0,0.5);
border:1px solid red;
}
.clcn2{
position:absolute;
width:30px;
height:30px;
background: yellow;
border:1px solid blue;
}
.none{
display:none;
}
<div class="clcn">
<div class="clcn2 none"></div>
</div>
<div class="clcn">
<div class="clcn2 none"></div>
</div>
<div class="clcn">
<div class="clcn2 none"></div>
</div>
<button onclick="displaySquares('none');">show squares</button>
Комментарии:
1. Использование
.querySelectorAll
вернет статический список, который не будет страдать от проблем live HTMLCollection, описанных ниже.function displaySquares(x){ let dr = document.querySelectorAll('.' x); dr.forEach(element => element.classList.remove(x));}
Ответ №1:
проблема в том, что вы меняете имя элементов на каждой итерации, поэтому
- на первой итерации у вас есть 3 элемента с классом none и I = 0, так что у вас есть элемент, затем вы удаляете 1, и теперь у вас есть 2
- на второй итерации у вас есть 2 элемента с классом none и I = 1, так что у вас есть элемент, затем вы удаляете 1, так что теперь у вас есть 1
- на третьей итерации у вас есть только 1 элемент с классом none в массиве «dr» и I = 2, поэтому у вас нет элемента в индексе 2, у вас есть только один элемент в индексе 1, поэтому dr[2] не определен
- решение, которое я принял, заключается в том, что я всегда получаю индекс первого элемента 0 и изменяю его
- причина, по которой это произошло, заключается в том, что dr является ссылкой на dom, поэтому, когда вы меняете dom, вы меняете dr, потому что это просто указатель на ссылку надеюсь, я помог
function displaySquares(x){
var dr = document.getElementsByClassName(x),pl=dr.length,i=0;
for (i; i < pl; i ) {
// fix
var lOb = dr[0];
if (lOb.classList) {
if (lOb.classList.contains(x)) {
lOb.classList.remove(x);
}
} else { //fallback for classList
var r = new RegExp("\b" x "\b", "g");
if (r.test(lOb.className)) {
lOb.className = lOb.className.replace(r, "");
}
}
}
}
.clcn{
width:130px;
height:130px;
background: rgba(0,0,0,0.5);
border:1px solid red;
}
.clcn2{
position:absolute;
width:30px;
height:30px;
background: yellow;
border:1px solid blue;
}
.none{
display:none;
}
<div class="clcn">
<div class="clcn2 none"></div>
</div>
<div class="clcn">
<div class="clcn2 none"></div>
</div>
<div class="clcn">
<div class="clcn2 none"></div>
</div>
<button onclick="displaySquares('none');">show squares</button>
Ответ №2:
Причина в том, что каждый раз, когда вы удаляете имя класса «none» из одного из элементов во время цикла, количество элементов в коллекции html (переменная «dr») изменяется. Итак, он начинается с 3, затем на следующей итерации это 2 и т.д. И поскольку вы увеличиваете «i», вы в основном пропускаете элемент.
Одним из возможных решений было бы использовать цикл while вместо цикла for, чтобы вы просто продолжали цикл, пока не останется никаких элементов.
while (dr.length) {
var lOb = dr[0];
if (lOb.classList) {
if (lOb.classList.contains(x)) {
lOb.classList.remove(x);
}
} else { //fallback for classList
var r = new RegExp("\b" x "\b", "g");
if (r.test(lOb.className)) {
lOb.className = lOb.className.replace(r, "");
}
}
}