Votre approche actuelle ajoute plusieurs gestionnaires click
à l'élément qui se déclenchent de manière séquentielle, en supprimant et ajoutant la classe plusieurs fois et avec des résultats imprévisibles en raison de la boucle imbriquée.
Les réponses existantes utilisent une solution en O(n) qui consiste à boucler sur tous les éléments de la liste, mais ce n'est pas nécessaire. Gardez simplement une référence du dernier élément sélectionné et supprimez la classe .active
de cet élément s'il est défini:
const list = [...document.querySelectorAll("ul li")];
let selectedEl;
for (const el of list) {
el.addEventListener("click", e => {
selectedEl && selectedEl.classList.remove("active");
selectedEl = e.target;
e.target.classList.add("active");
});
}
.active {
background: yellow;
}
Item 1
Item 2
Item 3
Une autre approche consiste à définir un attribut tabindex
pour chaque élément, puis à ajouter des écouteurs pour les événements focus
et blur
(ou focusin
/focusout
si vous voulez une propagation) qui peuvent capturer de manière plus précise les sémantiques de sélection/désélection que vous essayez d'atteindre. Déplacer le focus n'importe où désélectionnera l'élément de la liste, contrairement à l'approche de l'événement click
montrée ci-dessus.
for (const el of [...document.querySelectorAll("ul li")]) {
el.addEventListener("focus", e => e.target.classList.add("active"));
el.addEventListener("blur", e => e.target.classList.remove("active"));
}
.active {
background: yellow;
outline: none;
}
Item 1
Item 2
Item 3
Si vous cherchez à prendre en charge les anciens navigateurs, vous pouvez essayer (non testé):
var list = document.getElementsByTagName("li");
var selectedEl;
for (var i = 0; i < list.length; i++) {
list[i].addEventListener("click", function (e) {
if (selectedEl) {
selectedEl.className = selectedEl.className
.split(/\s+/)
.filter(function (e) { e !== "active"; })
.join(" ");
}
selectedEl = e.target;
e.target.className += " active";
});
}
.active {
background: yellow;
}
Item 1
Item 2
Item 3
ou
var list = document.getElementsByTagName("li");
for (var i = 0; i < list.length; i++) {
list[i].addEventListener("focusin", function (e) {
e.target.className += " active";
});
list[i].addEventListener("focusout", function (e) {
e.target.className = e.target.className
.split(/\s+/)
.filter(function (e) { e !== "active"; })
.join(" ");
});
}
.active {
background: yellow;
outline: none;
}
Item 1
Item 2
Item 3