不能在 forEach 函数中应用其他常量

Can't apply other const within a forEach function

我是 Javascript 的新手。

到目前为止,我的代码只更改了按钮文本的颜色,我试图在启用按钮的同时显示隐藏的段落。 总是说箭头和答案未定义

const buttons = document.querySelectorAll('button');
const answers = document.querySelectorAll('p');
const arrows = document.querySelectorAll('arrow');
console.log(buttons);
console.log(answers);
console.log(arrows);


buttons.forEach(button => {
    button.addEventListener('click', function(){
        button.style.color = 'red';
        answers.style.display = 'block';
    });
})

我做的替代代码是

const button = document.querySelector('button');
const answers = document.querySelector('.answer');
const arrow = document.querySelector('.arrow');


button.addEventListener('click', () => {
    answers.style.display = 'block';
    arrow.style.transform = 'rotate(180deg)'

});

这个成功了。但是,我必须标记 HTML 中需要更改的每个元素。

这是示例 HTML:

<div class="faq">
          <button>How many team members can I invite? <img class="arrow" src="images/icon-arrow-down.svg"></button>
          <p class="answer">You can invite up to 2 additional users on the Free plan. There is no limit on
          team members for the Premium plan.</p>
        </div>
        <div class="faq">
          <button>What is the maximum file upload size?<img class="arrow"src="images/icon-arrow-down.svg"> </button>
          <p class="answer"> No more than 2GB. All files in your account must fit your allotted storage space.</p>
        </div>
        <div class="faq">
          <button>How do I reset my password?<img class="arrow" src="images/icon-arrow-down.svg"></button>
          <p class="answer">Click “Forgot password” from the login page or “Change password” from your profile page.
            A reset link will be emailed to you.
          </p>
        </div>
        <div class="faq">
            <button>Can I cancel my subscription?<img class="arrow" src="images/icon-arrow-down.svg"></button>
          <p class="answer">Yes! Send us a message and we’ll process your request no questions asked.</p>
        </div>
        <div class="faq">
           <button>Do you provide additional support?<img class="arrow" src="images/icon-arrow-down.svg"></button>
          <p class="answer">Chat and email support is available 24/7. Phone lines are open during normal business hours.</p>
const buttons = document.getElementsByTagName('button');
const answers = document.getElementsByTagName('p');
const arrows = document.getElementsByTagName('arrow');
console.log(buttons);
console.log(answers);
console.log(arrows);


for (var j = 0; j < buttons.length; j++){
       var button = buttons[j];
       button.addEventListener('click', function(){
           button.style.color = 'red';
           for (var i = 0; i < answers.length; i++){
             answers[i].style.display = 'block'
           }        
    });
}

您应该使用 window.event.target 从单击事件处理程序中获取单击的元素。您的问题是试图从您的点击处理程序访问在其范围之外定义并具有不同含义的变量。每次调用点击处理程序时,它都需要一个策略来获取被点击的元素以及绑定到您希望更改样式的上下文的所有元素。

但有可能我没有正确理解您真正要问的问题...在这种情况下,我希望听到反馈。

我在这里做了一个演示来展示如何:

const buttons = document.querySelectorAll('button');

function resetButtonStyles(){
  document.querySelectorAll('div.parent.active').forEach( divactive =>{
    divactive.classList.remove('active');
  });
}

buttons.forEach(button => {
    button.addEventListener('click', function(){
    
      document.querySelector('div.parent.active')
        ?.classList.remove('active');

      const clickedButton = window.event.currentTarget;
      const parentDiv = clickedButton.closest('div.parent');
      const boundAnswer = parentDiv.querySelector('p');

      parentDiv.classList.add("active");

      //clickedButton.style.color = 'red';
      //boundAnswer.style.border = 'solid red 2px';
    });
})
.active p{
  color: red;
}

.active button{
  border: solid red 2px;
}
<div class="parent">
  <p>Answers 1</p>
  <button>Button 1</button>
</div>

<div class="parent">
  <p>Answers 2</p>
  <button>Button 2</button>
</div>

<div class="parent">
  <p>Answers 2</p>
  <button>Button 2</button>
</div>

<div class="parent">
  <p>Answers 2</p>
  <button>Button 2</button>
</div>

这听起来像是在追求手风琴效果。

  1. 将您的标记包装在容器中,以便您可以使用 event delegation

  2. 缓存容器和答案元素。

  3. 当您点击按钮隐藏所有答案时,切换箭头,然后显示该按钮的答案。

[注意:I've used unicode in CSS 显示箭头而不是图像]。

// Cache the elements
const container = document.querySelector('.container');
const answers = document.querySelectorAll('.answer');
const arrows = document.querySelectorAll('.arrow');

// Add a listener to the container
container.addEventListener('click', handleClick, false);

function handleClick(e) {

  // If we click a button
  if (e.target.matches('button')) {

    // Remove all the answers
    answers.forEach(answer => answer.classList.remove('show'));

    // Update the arrows
    arrows.forEach(arrow => {
      arrow.classList.remove('down');
      arrow.classList.add('right');
    });
    
    // Get the parent of the clicked element
    const parent = e.target.closest('.faq');

    // Change the arrow...
    const arrow = e.target.querySelector('.arrow');
    arrow.classList.remove('right');
    arrow.classList.add('down');
    
    // ...and then show the answer
    const answer = parent.querySelector('.answer');
    answer.classList.add('show');

  }

}
.answer { display: none; }
.show { display: block; }
.down:after { content: 'F783'; }
.right:after { content: 'F782'; }
button:hover { cursor: pointer; }
<div class="container">
  <div class="faq">
    <button>How many team members can I invite?
      <span class="arrow right"></span>
    </button>
    <p class="answer">You can invite up to 2 additional users on the Free plan. There is no limit on team members for the Premium plan.</p>
  </div>
  <div class="faq">
    <button>What is the maximum file upload size?
      <span class="arrow right"></span>
    </button>
    <p class="answer"> No more than 2GB. All files in your account must fit your allotted storage space.</p>
  </div>
  <div class="faq">
    <button>How do I reset my password?
      <span class="arrow right"></span>
    </button>
    <p class="answer">Click “Forgot password” from the login page or “Change password” from your profile page. A reset link will be emailed to you.
    </p>
  </div>
  <div class="faq">
    <button>Can I cancel my subscription?
      <span class="arrow right"></span>
    </button>
    <p class="answer">Yes! Send us a message and we’ll process your request no questions asked.</p>
  </div>
</div>