如何使用 JavaScript 关闭活动标签?

How can I close the active tab with JavaScript?

我有一个选项卡列表,如果用户点击某个选项卡,例如“Tab 1”然后它会显示位于此选项卡下的副本,如果他们单击“Tab 2”,则会显示此选项卡下的副本,而“Tab 1”下的副本将关闭,依此类推。

这按我想要的方式工作,但我正在努力解决的问题是,如果用户单击一个选项卡,我希望他们能够关闭同一个选项卡。如有任何帮助,我们将不胜感激。

document.querySelectorAll('.tabs-menu a').forEach(function(el) {
  el.addEventListener('click', function(event) {
    event.preventDefault();
    this.closest('.tabs-menu')
      .querySelector('.current')
      .classList.remove("current");
    this.closest('a').classList.add("current");
    document.querySelectorAll('.tab-content').forEach(function(a) {
      a.style.display = "none";
    });
    var activeTab = this.getAttribute("href");
    document.querySelector(activeTab).style.display = "block";
  });
});
.tab-content {
  display: none;
}
<ul class="tabs-menu">
  <li><a href="#tab-1">Tab 1</a></li>
  <div id="tab-1" class="current tab-content">tab 1 content</div>
  <li><a href="#tab-2">Tab 2</a></li>
  <div id="tab-2" class="tab-content">tab 2 content</div>
  <li><a href="#tab-3">Tab 3</a></li>
  <div id="tab-3" class="tab-content">tab 3 content</div>
  <li><a href="#tab-4">Tab 4</a></li>
  <div id="tab-4" class="tab-content">tab 4 content</div>
</ul>

您正在寻找离锚元素最近的锚元素。我怀疑那是你想要的。请记住,这始终指的是单击的元素,而不是您在上面的行中找到的元素。

然后,您只想对 current class 进行检查并采取相应措施:

document.querySelectorAll('.tabs-menu a').forEach(function(el) {
  el.addEventListener('click', function(event) {
    event.preventDefault();

    // if the tab is already active...
    if (this.classList.contains('current')) {

      // deactivate all tabs
      this.closest('.tabs-menu')
        .querySelector('.current')
        .classList.remove("current");

      // hide all tab panes
      document.querySelectorAll('.tab-content').forEach(function(pane) {
        pane.style.display = "none";
      });

      // otherwise...
    } else {

      // activate this tab
      this.classList.add("current");

      // hide all tab panes
      document.querySelectorAll('.tab-content').forEach(function(pane) {
        pane.style.display = "none";
      });

      // show the tab pane that correlates to this tab
      var activeTab = this.getAttribute("href");
      document.querySelector(activeTab).style.display = "block";
    }
  });
});
.tab-content {
  display: none;
}

a.current+.tab-content {
  display: block;
}
<ul class="tabs-menu">
  <li><a href="#tab-1">Tab 1</a></li>
  <div id="tab-1" class="tab-content">tab 1 content</div>

  <li><a href="#tab-2">Tab 2</a></li>
  <div id="tab-2" class="tab-content">tab 2 content</div>

  <li><a href="#tab-3">Tab 3</a></li>
  <div id="tab-3" class="tab-content">tab 3 content</div>

  <li><a href="#tab-4">Tab 4</a></li>
  <div id="tab-4" class="tab-content">tab 4 content</div>
</ul>

还有最后一个问题,那就是 forEach 循环是异步的,所以有时窗格不会显示,因为显示它的调用先于隐藏所有窗格的调用运行。您需要实施承诺或其他机制来处理该问题。 Read more

我再次查看了这个并创建了下面的内容,它看起来按照我想要的方式工作。

var acc = document.querySelectorAll('.tabs-menu li');
var i;
var open = null;
for (i = 0; i < acc.length; i++) {
  acc[i].addEventListener("click", function() {
    if (open == this) {
      open.classList.toggle("active");
      open = null;
    } else {
      if (open != null) {
        open.classList.toggle("active");
      }
      this.classList.toggle("active");
      open = this;
    }
  });
}
.tab-content {
  display: none;
}

.tabs-menu .active+.tab-content {
  display: block;
}
<ul class="tabs-menu">
  <li><a href="#tab-1">Tab 1</a></li>
  <div id="tab-1" class="tab-content">tab 1 content</div>

  <li><a href="#tab-2">Tab 2</a></li>
  <div id="tab-2" class="tab-content">tab 2 content</div>

  <li><a href="#tab-3">Tab 3</a></li>
  <div id="tab-3" class="tab-content">tab 3 content</div>

  <li><a href="#tab-4">Tab 4</a></li>
  <div id="tab-4" class="tab-content">tab 4 content</div>
</ul>