簡體   English   中英

單擊時將 class 添加到 HTML 列表中的一個且僅一個元素

[英]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屬性,然后為focusblur添加偵聽器(或者如果您想要冒泡,則添加焦點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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM