Почему classList.remove не работает, а jQuery .removeClass работает?

Я все еще привыкаю к ​​простому JavaScript и создаю базовый набор квадратных блоков div, которые будут добавлять и удалять классы при нажатии. Я использую массив, который добавит один из этих классов. При нажатии я хотел бы удалить все эти классы, прежде чем добавлять новый. Так, например, при нажатии на 2-й квадрат «класс B» будет добавлен только к этому, а затем при нажатии на любой другой квадрат он будет удален.

Я понимаю, что classList.remove должно быть раньше classList.add, но почему-то не работает. Я всегда получаю сообщение «Не удается прочитать свойство« удалить »неопределенного в HTMLDivElement.elem.addEventListener».

Однако, если я использую jQuery .removeClass, он работает без проблем. Но я бы предпочел не использовать jQuery.

Вот фрагмент. Вы можете увидеть classList.remove, что я пытался, в том, что закомментировано.

const addClass = ['classA','classB','classC','classD'];
const numbers = [0,1,2,3];
const square = document.querySelectorAll('.square');

square.forEach((elem, i) => {

  elem.addEventListener('click', () => {

    //square[i].classList.remove(...addClass)
    $(square).removeClass('classA classB classC classD');

    if (i == numbers[i]) {
      elem.classList.add(addClass[i]);
    }
  });
});
.square {
width: 2rem;
height: 2rem;
background-color: black;
margin: 1rem;
}

.classA { background-color: red; }
.classB { background-color: yellow; }
.classC { background-color: green; }
.classD { background-color: blue; }
<script src = "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class = "container">
	<div class = "square"></div>
	<div class = "square"></div>
	<div class = "square"></div>
	<div class = "square"></div>
</div>

Я просмотрел кучу других вопросов здесь и на других сайтах, но на самом деле не вижу этого.

Вы уверены, что хотите вызвать classList.remove() на square, а не на elem?

user3210641 26.02.2019 19:08

Это потому, что square — это NodeList. Попробуйте this.classList.remove().

EternalHour 26.02.2019 19:22
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
2
101
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Два метода, которые вы сравниваете, не эквивалентны:

square[i].classList.remove(...addClass)

Удалит все классы в массиве из элемента один.

$(square).removeClass('classA classB classC classD');

Удалит все эти классы из все квадратов.

Чтобы сделать это без jQuery, вы можете сделать:

square.forEach(elem => elem.classList.remove(...addClass));

const addClass = ['classA','classB','classC','classD'];
const numbers = [0,1,2,3];
const squares = document.querySelectorAll('.square');
// renamed square to squares so it's more obvious that it is a NodeList and not a single Node

squares.forEach((elem, i) => {

  elem.addEventListener('click', () => {

    squares.forEach(elem => elem.classList.remove(...addClass));

    if (i == numbers[i]) {
      elem.classList.add(addClass[i]);
    }
  });
});
.square {
width: 2rem;
height: 2rem;
background-color: black;
margin: 1rem;
}

.classA { background-color: red; }
.classB { background-color: yellow; }
.classC { background-color: green; }
.classD { background-color: blue; }
<script src = "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class = "container">
	<div class = "square"></div>
	<div class = "square"></div>
	<div class = "square"></div>
	<div class = "square"></div>
</div>

Однако они хотят, чтобы это было внутри события click (я полагаю, исходя из кода).

EternalHour 26.02.2019 19:25

@EternalHour Да, я обновил свой ответ фрагментом.

Kenmore 26.02.2019 19:32

Другие вопросы по теме