【问题标题】:Javascript event listener overwrites another event listenerJavascript 事件监听器覆盖另一个事件监听器
【发布时间】:2020-07-02 11:15:31
【问题描述】:

所以我正在尝试为移动设备创建多级导航,但遇到了一些问题。我还在学习 javascript,所以请和我一起裸露。这是codepen的链接:

https://codepen.io/maciekmat/pen/yLepYKq

因此,当您按下右上角的菜单时,会打开一个菜单。然后我希望能够进入子类别。例如,单击“测试打开”,将分配 .active 类,然后滑入另一个菜单。现在我想要一个返回按钮,它实质上删除了 .active 类。

无论我认为发生了什么,事件侦听器都会监听整个父级,并且您在子导航内单击的任何位置都会将其注册为单击,并运行 .active 类。当我单击返回时,它就像 .active 被删除并立即应用回来。有什么帮助吗?

我尝试执行 event.currentEvent !== event.target if 语句但没有运气

const nav = document.getElementById('menuIcon')
const dropdown = document.getElementById('menuDropdown')

nav.addEventListener('click', function() {
    dropdown.classList.toggle('nav-is-toggled')
});

const grabNavLinks = document.querySelectorAll('.sub-nav-link');
const grabBackLinks = document.querySelectorAll('.nav-link.back');
const subNavLinks = Array.from(grabNavLinks);
const backLinks = Array.from(grabBackLinks);

for (let i = 0; i < subNavLinks.length; i++) {
  subNavLinks[i].addEventListener("click", function() {
  this.querySelector('.sub-nav').classList.add('active');
  });
}

for (let i = 0; i < backLinks.length; i++) {
  backLinks[i].addEventListener("click", function() {
    document.querySelector('.sub-nav').classList.remove('active');
  });
}
@import url("https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;600;700&display=swap");
* {
  box-sizing: border-box;
}

body {
  margin: 0;
  padding: 0;
  font-family: "Open sans", sans-serif;
  background: #F9F9F9;
  box-sizing: border-box;
}

a, p, h1, h2, h3 {
  margin: 0;
  padding: 0;
  text-decoration: none;
}

ul, li {
  padding: 0;
  margin: 0;
}

header {
  background: white;
  padding: 24px 30px;
  display: flex;
  flex-direction: column;
  z-index: 10;
  position: relative;
}

.top-nav {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.top-nav .logo {
  background: url("images/tcb-logo-brand.svg") no-repeat;
  width: 150px;
  height: 50px;
  background-size: contain;
  background-position: center;
}
.top-nav .navigation {
  display: flex;
  justify-content: space-between;
  width: 132px;
  height: 26px;
}
.top-nav .navigation .nav-item {
  width: 23px;
  height: 26px;
  margin-left: 10px;
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
}
.top-nav .navigation .nav-item.menu {
  background-image: url("images/menu-icon.svg");
}
.top-nav .navigation .nav-item.notification {
  background-image: url("images/bell-icon.svg");
}
.top-nav .navigation .nav-item.my-account {
  background-image: url("images/acc-icon.svg");
}

.search {
  margin-top: 16px;
}
.search input[type=search] {
  outline: none;
  border: none;
  background: #F6F6F6;
  width: 100%;
  height: 50px;
  font-size: 16px;
  padding: 10px 0 10px 20px;
  background-image: url("images/search-icon.svg");
  background-repeat: no-repeat;
  background-position: right 15px top 50%;
}
.search input[type=search]::placeholder {
  color: #B7B7B7;
}

span.nav-title {
  display: none;
}

nav.main-nav {
  width: 100%;
  background: #F6F6F6;
  transform: translateY(-100%);
  z-index: 0;
  position: relative;
  transition: all 0.3s ease-in-out;
  position: absolute;
  padding-bottom: 50px;
  overflow: hidden;
}
nav.main-nav ul {
  padding-top: 2px;
  position: relative;
}
nav.main-nav li {
  list-style: none;
}
nav.main-nav a {
  color: #6D6D6D;
  font-size: 16px;
  width: 100%;
  height: 100%;
  display: block;
  padding: 18px 30px;
  border-bottom: 1px solid #E9E9E9;
}
nav.main-nav li.nav-link.arrow {
  background: url("images/right-arrow.svg") no-repeat;
  background-position: right 30px top 50%;
}
nav.main-nav ul.sub-nav {
  background: #cecece;
  width: 100%;
  display: flex;
  flex-direction: column;
  transform: translateX(100%);
  overflow: hidden;
  visibility: hidden;
  opacity: 0;
  position: absolute;
  top: 0;
  left: 0;
  transition: transform 0.2s ease;
}

.sub-nav-link > .sub-nav.active {
  transform: translateX(0);
  visibility: visible;
  opacity: 1;
}

nav.nav-is-toggled {
  position: static;
  opacity: 1;
  transform: translateY(0);
  transition: all 0.3s ease-in-out;
}
    <header>
        <div class="top-nav">
            <div class="logo"></div>
            <div class="navigation">
                <div id="menuIcon" class="nav-item menu">test</div>
                <div class="nav-item notification"></div>
                <div class="nav-item my-account"><span class="nav-title">My Account</span></div>
            </div>
        </div>
        <div class="search">
            <input type="search" name="search" id="search" placeholder="Search by store...">
        </div>
    </header>

    <nav id="menuDropdown" class="main-nav">
        <ul class="main-nav-ul">
            <li class="nav-link"><a href="#">Test</a></li>
            <li class="nav-link arrow sub-nav-link"><a href="#">Test Open</a>
                <ul class="sub-nav">
                    <li class="nav-link back"><a href="#">Go Back</a></li>
                    <li class="nav-link"><a href="#">Test</a></li>
                    <li class="nav-link"><a href="#">Test</a></li>
                    <li class="nav-link"><a href="#">Test</a></li>
                </ul>
            </li>
            <li class="nav-link"><a href="#">Test</a></li>
            <li class="nav-link"><a href="#">Test</a></li>
            <li class="nav-link arrow sub-nav-link"><a href="#">Test Open</a>
                <ul class="sub-nav">
                    <li class="nav-link back"><a href="#">Go Back</a></li>
                    <li class="nav-link"><a href="#">Test</a></li>
                    <li class="nav-link"><a href="#">Test</a></li>
                </ul>
            </li>
            <li class="nav-link"><a href="#">Test</a></li>
        </ul>
    </nav>
    <script src="navigation.js"></script>

【问题讨论】:

  • 这解决了您的问题吗?

标签: javascript html css navigation addeventlistener


【解决方案1】:

阅读事件冒泡以及它如何在 DOM 树中冒泡。然而,由于它从父级传递到子级的方式(即它在树中冒泡),您应该调用 event.stopPropagation(); 以便前一个事件不会冒泡到 backLinks 事件侦听器中。

这是你应该做的

for (let i = 0; i < backLinks.length; i++) {
  backLinks[i].addEventListener("click", function(event) {
    event.stopPropagation();
    document.querySelector('.sub-nav').classList.remove('active');
  });
}

【讨论】:

  • 嘿!非常感谢您的回答,我之前尝试过上述解决方案,但是对于您的 cmets,我意识到这可能不是最好的解决方案,谢谢您指出!我已经使用了您的上述建议,并且效果很好,我目前正在阅读有关事件传播和通过 DOM 进行翻译的更多信息。后退按钮仅在顶部按钮上不起作用,但我嵌套了所有后退按钮/子导航的数组的 for 循环,并在那里应用了删除类。现在就像一个魅力!你会说上面的代码,或者其他的,看起来没问题吗?还是更好的方法?
  • @Mac 没关系,我会做不同的事情,但我相信每个人都有他/她的过程。你获得的经验越多,你的代码组合就越好,但我看到你已经坚持使用 let 而不是 var 所以这对你来说是一个加分
猜你喜欢
  • 1970-01-01
  • 2020-06-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-14
  • 2019-04-13
相关资源
最近更新 更多