1

我尝试添加“活动类”,当用户单击它时,它将改变导航项的颜色(通过 li 标签显示)。为此,我创建了一个函数来删除所有 li 元素中的活动类。之后,当点击导航项时,我会将活动类添加到该元素。问题是,在运行我的代码时,不是只有一项具有“活动”类,而是所有项都有。我为这个问题找到了很多解决方案,但大多数都使用 jQuery,我对这个库一无所知。我希望有人可以在下面指出我的代码错误。谢谢!

// Find all li tags
const liTags = document.querySelectorAll('li');

// Function to remove the current element has active class
function RemoveActive() {
    for (let i = 0; i < liTags.length; i++) {
        const currentActiveClass = document.querySelector('.active');
        // Remove active class in the current li element
        if (currentActiveClass != null) {
            liTags[i].classList.remove('active');
        }
    }   
}

// Add the active class to the clicked item
for (let i = 0; i < liTags.length; i++) {
    liTags[i].addEventListener('click', function() {
        RemoveActive;
        liTags[i].classList.add('active');
    })
}
4

4 回答 4

1

正如您从我的示例中看到的那样,我添加而不是检查元素,然后您在函数classList.contains中出现拼写错误()

// Find all li tags
const liTags = document.querySelectorAll('li');

function RemoveActive() {
    for (let i = 0; i < liTags.length; i++) {
        if (liTags[i].classList.contains('active')) {
            liTags[i].classList.remove('active');
        }
    }   
}

for (let i = 0; i < liTags.length; i++) {
    liTags[i].addEventListener('click', function() {
        RemoveActive();
        liTags[i].classList.add('active');
    })
}
.active{
  background-color:red;
}
<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
</ul>

而不是使用removeadd您可以使用toggle如下:

// Find all li tags
const liTags = document.querySelectorAll('li');

function RemoveActive() {
  const li = document.querySelector('li.active')
  if (li) {
    li.classList.toggle("active");
  }
}

for (let i = 0; i < liTags.length; i++) {
  liTags[i].addEventListener('click', function() {
    RemoveActive();
    liTags[i].classList.toggle('active');
  })
}
.active {
  background-color: red;
}
<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
</ul>

于 2021-09-17T13:38:41.453 回答
0

我相信你的错误是 RemoveActive;它应该是 RemoveActive(),但我想我会花时间重构代码。

我建议对函数名称 removeActive() 使用驼峰式大小写,并将它们命名为比“RemoveActive”更具描述性的名称,因为这将使未来的开发/理解该函数随着程序的增长而发挥的作用更容易。

const navigationItems = document.querySelectorAll('li');

function toggleActiveNavItem() {
  navigationItems.forEach(item => {
    item.addEventListener("click", function() {
      addClickEventToNavigation(item)
    }
  }
}

function addClickEventToNavigation(item) {
  // Remove active from every navigation item
  navigationItems.forEach(individualNavigationItem =>{
    // Other than the one passed to the function as having been clicked
    if (individualNavigationItem != item) {
      individualNavigationItem.classList.remove("active");
    }

    // If the clicked item does not have the active class, add it
    if (!item.classList.contains("active")) {
      individualNavigationItem.classList.add("active");
    }
  });
}
于 2021-09-17T13:48:12.020 回答
0

您应该遵循这种做法以获得干净和更少的代码

var root = document.querySelector(".root")

root.addEventListener("click",e=>{
  var t = e.target,
      li = t.closest("li")
  if(li){
    root.querySelectorAll("li").forEach(each=>each.classList.remove("active")) 
    li.classList.add("active")
  }
})
.active {
  background:blue;
  color:white;
}

.root li {
  padding:2px;
  cursor:pointer;
} 
<ul class="root">
  <li class="active">items</li>
  <li>items</li>
  <li>items</li>
  <li>items</li>
  <li>items</li>
  <li>items</li>
  <li>items</li>
</ul>

于 2021-09-17T13:49:34.900 回答
0

从上面对OP问题的直接评论......

“不管是什么导致了故障,重新考虑整个方法。现在,在查询时向下可用的每个 LI 元素document都具有自己的点击处理功能。即使可以做到这一点(而不是事件委托),也会出现一个更大的问题。是整个文档中只有一个无序列表?如果没有,请注意当前方法将适用于不同列表的活动状态......意味着,从随机列表中单击的任何项目都会删除active类名(如果存在)来自其他列表的任何其他列表项。”

下面的下一个示例仅用于演示目的,目的是展示使用基于事件委托的方法可以实现什么......

function getNestedListRoot(listNode) {
  let elmNode = listNode;
  while (listNode = listNode?.parentNode.closest('ol, ul')) {
    elmNode = listNode;
  }
  return elmNode;
}

function handleNestedListItemsActiveState({ target }) {
  // the LI element closest to the `click` source.
  const srcLiElm = target.closest('li');

  // guard
  if (srcLiElm === null) {
    return;
  }
  // the LI element's un/ordered list parent.
  const listNode = srcLiElm.parentNode;
  // the top most un/ordered list node
  // of a nested list structure.
  const listRoot = getNestedListRoot(listNode);

  listRoot
    .querySelectorAll('li')
    .forEach(elmNode =>
      // de'active'ate every LI element
      // within the nested list structure.
      elmNode.classList.remove('active')
    );
  let liElm = srcLiElm;

  while (liElm) {
    // follow the path of directly nested
    // LI elements from the current inner to the
    // most outer LI element and 'active'ate each.    
    liElm.classList.add('active');

    liElm = liElm.parentNode.closest('li');
  }
}

function initialize() {
  document
    .querySelectorAll('ol, ul')
    .forEach(elmNode =>
      elmNode.addEventListener('click', handleNestedListItemsActiveState)
    )
}
initialize();
body { margin: -2px 0 0 0; }
ol, ul { margin: 0 0 10px 0; }
ol ul, ul ol, ol ol, ul ul { margin: 0; }
li { margin: 0 0 0 -20px; font-size: 12px; }
li.active,
li.active li.active { color: #fc0; }
li.active li { color: initial; }
<ol>
  <li class="active">
    OL_A-a
    <ul>
      <li>
        OL_A-a__UL_A-a
      </li>
      <li class="active">
        OL_A-a__UL_A-b
        <ol>
          <li>
            OL_A-a__UL_A-b__OL_B-a
          </li>
          <li>
            OL_A-a__UL_A-b__OL_B-b
          </li>
          <li class="active">
            OL_A-a__UL_A-b__OL_B-c
          </li>
        </ol>
      </li>
      <li>
        OL_A-a__UL_A-c
      </li>
    </ul>
  </li>
  <li>
    OL_A-b
  </li>
  <li>
    OL_A-c
    <ul>
      <li>
        OL_A-c__UL_B-a
      </li>
      <li>
        OL_A-c__UL_B-b
      </li>
      <li>
        OL_A-c__UL_B-c
      </li>
    </ul>
  </li>
</ol>

<ol>
  <li>
    OL_A-a
    <ul>
      <li>
        OL_A-a__UL_A-a
      </li>
      <li>
        OL_A-a__UL_A-b
        <ol>
          <li>
            OL_A-a__UL_A-b__OL_B-a
          </li>
          <li>
            OL_A-a__UL_A-b__OL_B-b
          </li>
          <li>
            OL_A-a__UL_A-b__OL_B-c
          </li>
        </ol>
      </li>
      <li>
        OL_A-a__UL_A-c
      </li>
    </ul>
  </li>
  <li>
    OL_A-b
  </li>
  <li class="active">
    OL_A-c
    <ul>
      <li class="active">
        OL_A-c__UL_B-a
      </li>
      <li>
        OL_A-c__UL_B-b
      </li>
      <li>
        OL_A-c__UL_B-c
      </li>
    </ul>
  </li>
</ol>

于 2021-09-17T15:46:16.820 回答