【问题标题】:Click Event Shows And Removes All Overlays Instead Of Individually - JavaScript单击事件显示并删除所有覆盖而不是单独 - JavaScript
【发布时间】:2021-05-04 20:30:50
【问题描述】:

我有一个我想要的包装容器,所以当我点击每条信息仅针对该包装显示的名称时,当我单击/关闭“x”按钮时,它只会为该按钮删除它。

使用forEach() 方法,它会显示并删除所有内部容器,除了那些被点击的容器。

我认为可以使用 this 关键字,但我无法让它工作。

我是 Javascript 新手,因此非常感谢任何帮助。

Codepen:https://codepen.io/anna_paul/pen/JjWPLjx

window.addEventListener('DOMContentLoaded', function() {
  
  let name = document.querySelectorAll('.name')
  let close = document.querySelectorAll('.close')
  let innerText = document.querySelectorAll('.inner-text')

  // ----- show text
  name.forEach(function(item){

      item.addEventListener('click', function(){

          innerText.forEach(function(inner){
              inner.classList.add('active')
          })

      }, false)

  })

  // ---- hide text
  close.forEach(function(item){

      item.addEventListener('click', function(){

          innerText.forEach(function(inner){
             inner.classList.remove('active')
          })

      }, false)

  })
  
}) // DomContentLoaded
* {position: relative; box-sizing: border-box;}

body {
  margin: 0;
  height: 100vh;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}

.wrapper {
  width: 10rem;
  background: #fafafa;
  padding: 1rem;
  margin: 1rem;
}

.inner-text {
  background: red;
  display:none;
}

.inner-text.active {
    display: block
}

.close {
    position: absolute;
    top: -5rem;
    right: 0rem;
    padding: .5rem;
    background: white;
    z-index: 2;
}

.name {
  background: yellow;
  padding: 1rem;
  cursor: pointer;
}
<div class="wrapper">
  <p class="name">Name</p>
  <div>Other content</div>
  <div class="inner-text">
    <div class="close">x</div>
    <ul>
      <li>INFO</li>
      <li>INFO</li>
      <li>INFO</li>
      <li>INFO</li>
      <li>INFO</li>
    </ul>
  </div>
</div>

<div class="wrapper">
  <p class="name">Name</p>
  <div>Other content</div>
  <div class="inner-text">
    <div class="close">x</div>
    <ul>
      <li>INFO</li>
      <li>INFO</li>
      <li>INFO</li>
      <li>INFO</li>
      <li>INFO</li>
    </ul>
  </div>
</div>

【问题讨论】:

    标签: javascript foreach onclick dom-events


    【解决方案1】:

    您几乎已经确定了问题中的问题,即您正在遍历事件处理程序中的所有面板并向所有面板添加/删除类。相反,您可以使用“事件委托”,在所有面板的共同祖先中仅设置一个事件处理程序,并让事件“冒泡”到该祖先并在那里处理。另外,由于 show 和 hide 的代码非常相似,您可以只为两者使用一个函数。

    最后,innerText 不是一个很好的变量名称,因为innerText 实际上是一个 DOM 元素属性名称。

    // If you place the script that holds this code just before the
    // closing BODY tag, you won't need to set up a DOMContentLoaded
    // event.
    
    document.querySelector(".masterWrapper").addEventListener("click", function(event){
      // Check to see if the event originated at an element
      // we care about handling
      
      // Get a reference to the <div class="wrapper"> ancestor of the clicked element
      // and then find the <div class="inner-text"> descedant within it.
      const inner_text = event.target.closest(".wrapper").querySelector(".inner-text");
      
      // When Name is clicked
      if(event.target.classList.contains("name")){
        // If the panel is not already showing its content:
        if(!inner_text.classList.contains("active")){
          inner_text.classList.add("active");
        }
      }
      
      // When the X is clicked
      if(event.target.classList.contains("close")){
          event.target.parentElement.classList.remove("active");
      }  
    
    });
    * {position: relative; box-sizing: border-box;}
    
    body {
      margin: 0;
      height: 100vh;
      width: 100%;
      display: flex;
      align-items: center;
      justify-content: center;
    }
    
    .wrapper {
      width: 10rem;
      background: #fafafa;
      padding: 1rem;
      margin: 1rem;
    }
    
    .inner-text {
      background: red;
      display:none;
    }
    
    .inner-text.active {
        display: block
    }
    
    .close {
        position: absolute;
        top: -5rem;
        right: 0rem;
        padding: .5rem;
        background: white;
        z-index: 2;
    }
    
    .name {
      background: yellow;
      padding: 1rem;
      cursor: pointer;
    }
    <div class="masterWrapper">
      <div class="wrapper">
        <p class="name">Name</p>
        <div>Other content</div>
        <div class="inner-text">
          <div class="close">x</div>
          <ul>
            <li>INFO</li>
            <li>INFO</li>
            <li>INFO</li>
            <li>INFO</li>
            <li>INFO</li>
          </ul>
        </div>
      </div>
    
      <div class="wrapper">
        <p class="name">Name</p>
        <div>Other content</div>
        <div class="inner-text">
          <div class="close">x</div>
          <ul>
            <li>INFO</li>
            <li>INFO</li>
            <li>INFO</li>
            <li>INFO</li>
            <li>INFO</li>
          </ul>
        </div>
      </div>
    </div>

    【讨论】:

    • 谢谢@ScottMarcus 我想我可能需要编辑这个问题。我简化了标记以使其更易于阅读,但它不会成为完整版本的兄弟元素。我需要引用变量名。我虽然“这”可能有用,但不能让它打球。
    • @Anna_p 它不一定是兄弟姐妹。不管是什么关系,都有一种方法可以在没有 id 或显式引用的情况下引用它。只需编辑您的问题以显示真正的层次结构。
    • 如果我添加完整的代码,任何人都无法回答这个问题:这是一个我接管的网站,它有大约 10 层深的真正毫无意义的 html。当单击该包装器的名称时,我只需要在每个单独的“包装器”元素中找到方法,内部文本就会显示,并且当在该单个包装器内单击“关闭”元素时,它会被删除。我以为我可以纯粹通过引用变量名来做到这一点?
    • 我已经编辑了这个问题以使其更清晰。
    • @Anna_p 虽然 HTML 层可能很复杂,但您确实应该展示一个示例,说明其中至少一个的结构。我真的不知道您所说的引用变量名是什么意思,因为仍然必须将变量设置为元素。
    猜你喜欢
    • 2021-05-06
    • 1970-01-01
    • 2020-11-12
    • 2014-12-02
    • 1970-01-01
    • 1970-01-01
    • 2016-12-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多