[英]Add a class to one and only one element from an HTML list on click
我有一個這樣的列表:
<ul>
<li class="item">Item 1</li>
<li class="item">Item 2</li>
<li class="item">Item 3</li>
</ul>
我需要將活動的 class 單獨添加到每個項目中,然后單擊前一個項目將其刪除。
類似於這個問題的東西Vanilla JS remove class from previous selection但是由於舊的瀏覽器兼容性,我需要使用 For 循環而不是 ForEach 。
我一直在嘗試使該答案適應我的示例:
const items = document.querySelectorAll(".item");
for (let i = 0; i < items.length; i++) {
const item = items[i];
item.addEventListener("click", addActiveClass);
for (let i = 0; i < items.length; i++) {
const item = items[i];
item.addEventListener("click", removeClass);
}
}
function removeClass(e) {
e.target.classList.remove("active");
}
function addActiveClass(e) {
e.target.classList.add("active");
}
但它仍然沒有按預期工作:(
我假設您需要從項目的 rest 中刪除活動的 class,然后更新正確的項目。 但是,我不確定classList
在您尋求支持的舊瀏覽器中是否可用。 您應該查看用於較舊的弓箭手的polyfill 。
const items = document.querySelectorAll(".item");
for (let i = 0; i < items.length; i++) {
const item = items[i];
item.addEventListener("click", changeActiveClass);
}
function changeActiveClass(e)
{
for (let i = 0; i < items.length; i++) {
const item = items[i];
item.classList.remove('active');
}
e.target.classList.add('active');
}
您當前的方法將多個click
處理程序添加到按順序觸發的元素中,多次刪除和添加 class 並且由於嵌套循環而導致不可預測的結果。
現有答案使用 O(n) 解決方案,該解決方案涉及遍歷列表中的所有元素,但沒有必要這樣做。 只需保留對最后一個選定元素的引用並從該元素中刪除.active
class (如果已定義):
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; }
<ul> <li class="item">Item 1</li> <li class="item">Item 2</li> <li class="item">Item 3</li> </ul>
另一種方法是為每個元素設置一個tabindex
屬性,然后為focus
和blur
添加偵聽器(或者如果您想要冒泡,則添加焦點focusin
/ focusout
),這可以更准確地捕獲您嘗試實現的選擇/取消選擇語義。 將焦點移動到任何地方都會取消選擇列表項,這與上面顯示的click
事件方法不同。
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; }
<ul> <li class="item" tabindex="-1">Item 1</li> <li class="item" tabindex="-1">Item 2</li> <li class="item" tabindex="-1">Item 3</li> </ul>
如果您希望支持舊版瀏覽器,您可以嘗試(未經測試):
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; }
<ul> <li class="item">Item 1</li> <li class="item">Item 2</li> <li class="item">Item 3</li> </ul>
或者
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; }
<ul> <li class="item" tabindex="-1">Item 1</li> <li class="item" tabindex="-1">Item 2</li> <li class="item" tabindex="-1">Item 3</li> </ul>
您需要稍微更改 for 循環:
for (let i = 0; i < items.length; i++) {
const clickedItem = items[i];
// Add an event listener to each item
clickedItem.addEventListener("click", function() {
// Remove class from all items
for (let j = 0; j < items.length; j++) {
const item = items[j];
item.classList.remove("active");
}
// Add class to the clicked item
clickedItem.classList.add("active");
});
}
請注意,您也可以使用箭頭 function,但如果您要向后兼容,最好使用function
。
這看起來是一個很好的事件委托候選者。 代碼可以重寫為類似
document.addEventListener("click", addActive); function addActive(evt) { if (evt.target.classList.contains("item")) { // remove.active from all li.active const allItems = document.querySelectorAll(".active"); for (let i=0; i<allItems.length; i += 1) { allItems[i].classList.toggle("active"); } // add.active to the current (clicked) item evt.target.classList.toggle("active"); } }
li.item { cursor: pointer; }.active { color: red; }
<ul> <li class="item">Item 1</li> <li class="item">Item 2</li> <li class="item">Item 3</li> </ul>
你可以嘗試這樣的事情:
const items = document.querySelectorAll(".item"); for (let i = 0; i < items.length; i++) { const item = items[i]; item.addEventListener("click", toggleActive); } function cleanActiveClasses() { for (let i = 0; i < items.length; i++) { const item = items[i]; item.className = item.className.replace(/(?:^|\s)active(?,\S)/g; '') } } function toggleActive(e) { cleanActiveClasses(). e.target;className += " active"; }
.active { color: red; }
<ul> <li class="item">Item 1</li> <li class="item">Item 2</li> <li class="item">Item 3</li> </ul>
添加了一些 css 只是為了給您視覺反饋。
簡而言之:DOM 元素上只有一個偵聽器,它在分配新的 class 之前清理每個元素。
希望能幫助到你。
編輯:由於您要求這樣做是為了向后兼容,舊的 IE 版本不支持 classList。 使用 className 和正則表達式編輯了一個新版本,以刪除活動的 class。
這將根據需要添加/刪除類。 此外,最好檢查並確保您要查找的元素.item
確實在頁面上。
const items = document.querySelectorAll(".item"); for (let i = 0; i < items.length; i++) { const item = items[i]; item.addEventListener("click", () => { for (let i = 0; i < items.length; i++) { const item = items[i]; item.classList.remove("active"); } item.classList.add("active"); }); }
.item:hover { cursor: pointer; }.active { color: blue; }
<div> <ul> <li class="item">Item 1</li> <li class="item">Item 2</li> <li class="item">Item 3</li> </ul> </div>
您只需要在click
事件的一個處理程序中執行此操作。
const items = document.querySelectorAll(".item"); for (let i = 0; i < items.length; i++) { const item = items[i]; item.addEventListener("click", (e) => toggleActiveClass(e, items)); } function toggleActiveClass(e) { for (let i = 0; i < items.length; i++) { const item = items[i]; item.classList.remove("active"); } e.target.classList.add("active"); }
.item.active { color: red; }
<ul> <li class="item">Item 1</li> <li class="item">Item 2</li> <li class="item">Item 3</li> </ul>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.