【问题标题】:Prevent buttons with same class from being clicked simultaneously防止同时单击具有相同类的按钮
【发布时间】:2021-02-27 15:44:47
【问题描述】:

我有两个按钮具有相同的类名和相同的功能,但必须添加不同的输入,所以我使用document.querySelectorAll() 和forEach() 方法来获取它们,但是现在当我单击一个时,另一个获取也点击了。有没有办法在两个按钮都没有两个addEventListener 的情况下防止这种情况发生?让它一次只点击一个按钮。

我的代码:

let inputElements = document.querySelectorAll('.inputElement');
const submitBtn = document.querySelectorAll('.submitBtn');
const backersElement = document.querySelector('.number-of-backers');

let donationsMade = [];

function calculateBamboo() {

    inputElements.forEach(inputElement => {
        const inputValue = parseFloat(inputElement.value);

        if (inputValue < 25 || inputValue === '') return alert('Pledge must be at least $25.');
        
        donationsMade.push(inputValue);
        const donationsTotal = donationsMade.reduce((a, b) => a += b);
        pledgedAmount.textContent = `$${donationsTotal}`;
        backersElement.textContent = donationsMade.length;

        return donationsTotal;

    })
}
submitBtn.forEach(button => {
    button.addEventListener('click', calculateBamboo);
})

【问题讨论】:

    标签: javascript button foreach event-handling


    【解决方案1】:

    实际上并不是“点击”两个按钮。发生的事情如下:

    您的calculateBamboo() 函数循环遍历所有输入元素:inputElements.forEach();你正在为所有输入执行你的逻辑。因此,无论您按下哪个按钮,calculateBamboo() 都会处理每个输入。

    使用数据属性传递目标输入将帮助您识别哪个输入属于点击按钮

    另外,@JerryBen 是对的,您不需要为每个按钮添加事件侦听器,相反,我们可以将所有按钮 包装 在一个元素中,为其添加事件侦听器并识别哪个元素被点击。

    const wrapper = document.getElementById('wrapper');
    const pledgedAmount = document.querySelector('.backed-users');
    const backersElement = document.querySelector('.number-of-backers');
    
    wrapper.addEventListener('click', calculateBamboo);
    
    let donationsMade = [];
    
    function calculateBamboo(event) {
      /* Here you can access to the event argument,
        which contains target: the clicked element*/
      const el = event.target;
    
      if (el.nodeName !== 'BUTTON' || !el.classList.contains('submitBtn')) {
        return;
      }
    
      // Get target input from button's data-attr
      const targetInput = el.dataset.input;
      const inputElement = document.querySelector(`input[data-input="${targetInput}"]`);
    
      // Continue with the code you had...
      const inputValue = parseFloat(inputElement.value) || 0;
    
      if (inputValue < 25 || inputValue === '') return alert('Pledge must be at least $25.');
    
      donationsMade.push(inputValue);
      const donationsTotal = donationsMade.reduce((a, b) => a += b);
      pledgedAmount.textContent = `$${donationsTotal}`;
      backersElement.textContent = donationsMade.length;
    
      return donationsTotal;
    }
    <div class="backed">
      <h1 class="backed-users">0</h1>
    </div>
    
    <div class="backers">
      <h1 class="number-of-backers">0</h1>
    </div>
    
    <hr>
    
    <div id="wrapper">
      <div class=".pledge-edition">
        <div class="pledge">
          <section class="pledgeTwo"></section>
          <div>
            <h2>Bamboo Stand</h2>
            <a href="#">Pledge $25 or more</a>
            <div>
              <h2>101</h2>
              <div>left</div>
            </div>
          </div>
        </div>
    
        <p>
          You get an ergonomic stand made of natural bamboo. You've helped us launch our promotional campaign, and you’ll be added to a special Backer member list.
        </p>
    
        <div class="pledge-amount">
          <p>Enter your pledge</p>
          <div>
            <input class="inputElement bambooInputElement" data-input="1" placeholder="$25" min="25" type="number">
            <button class="submitBtn bambooBtn" data-input="1">Continue</button>
          </div>
        </div>
      </div>
    
      <div class=".pledge-edition">
        <div class="pledge">
          <section class="pledgeThree"></section>
          <div>
            <h2>Black Edition Stand</h2>
            <a href="#">Pledge $75 or more</a>
            <div>
              <h2>64</h2>
              <div>left</div>
            </div>
          </div>
        </div>
    
        <p>
          You get a Black Special Edition computer stand and a personal thank you. You’ll be added to our Backer member list. Shipping is included.
        </p>
    
        <div class="pledge-amount">
          <p>Enter your pledge</p>
          <div>
            <input class="inputElement bambooInputElement" data-input="2" placeholder="$75" min="75" type="number">
            <button class="submitBtn blackEditionBtn" data-input="2" placeholder="$75" min="75">Continue</button>
          </div>
        </div>
      </div>
    </div>

    【讨论】:

    • 我不确定它是否有效我选择了第二个选项“使用数据属性传递目标输入”但是这些元素没有显示输入的值backersElement.textContent = donationsMade.length; pledgedAmount.textContent = `$${donationsTotal};
    • 这个工作 backersElement.textContent = donationsMade.length; 但另一个返回 null
    • 我认为这应该可行。我做了一个小的调整来添加下面提到的一个好的实践,并使这个例子更加...明确,因为我注意到你漏掉了一行(这也是你在下面提到的错误的原因)。如果还有其他问题或您不理解某些内容,请在此处告诉我,以便我可以跟踪您的 cmets 并更新答案。 ;)
    • 仍然无法正常工作,我认为这种方法是因为我的按钮不在同一个容器上,请在下面查看我的答案我已经更新了我的 HTML
    • 我有几个错别字,但逻辑是正确的。更正它并使用您更新的 HTML 进行测试:它有效。复制/粘贴此代码应该适合您,但我建议您无论如何都要分析它,以便您了解正在发生的事情。在那里你有一个 sn-p 可以看到它的工作。
    【解决方案2】:

    向每个按钮添加事件侦听器被认为是一种不好的做法。相反,使用单个事件侦听器来统治它们:

    1. 将按钮包装在 div 元素中
    2. 仅将点击事件添加到 div 包装器
    3. 将event 对象作为参数传递给处理函数
    4. 事件处理函数将使用event.target 来识别单击了哪个特定按钮:

    function calculateBamboo(evt){ const inputValue = parseFloat(evt.target.value) }

    我希望这会有所帮助?

    【讨论】:

    • 我考虑过这个我不确定它是否会起作用按钮位于页面的不同部分。如果我将它们包装在具有相同类名的 div 上会起作用吗
    • 你能提供一个带有HTML + JS的代码sn-p吗?
    • 请查看我发布的 sn-ps 的答案
    • 您的代码只包含一个按钮元素。我错过了什么吗?
    • 对不起,我以为我复制了整个代码,我刚刚编辑了它
    【解决方案3】:

    我现在的 JS

    function calculateBamboo(target) {
    
        let inputElement = document.querySelector(`input[data-input="${target}"]`);
            donationsMade.push(inputElement);
            const donationsTotal = donationsMade.reduce((a, b) => a += b);
            backersElement.textContent = donationsMade.length;
            pledgedAmount.textContent = `$${donationsTotal}`;
            successElement.style.display = 'block';
            return donationsTotal;
    }
    submitBtn.forEach(button => {
        const target = button.dataset.input;
        button.addEventListener('click', calculateBamboo.bind(target));
    })
    

    HTML 按钮和输入

    <!-- this is how my buttons are placed -->
    <div id="wrapper">
    <div class=".pledge-edition">
            <div class="pledge">
              <section class="pledgeTwo"></section>
              <div>
                <h2>Bamboo Stand</h2>
                <a href="#">Pledge $25 or more</a>
                <div>
                  <h2>101</h2>
                  <div>left</div>
                </div>
              </div>
            </div>
    
            <p>
              You get an ergonomic stand made of natural bamboo. You've helped us launch our promotional campaign, and
              you’ll be added to a special Backer member list.
            </p>
    
            <div class="pledge-amount">
              <p>Enter your pledge</p>
              <div>
                <input class="inputElement bambooInputElement" data-input="1" placeholder="$25" min="25" type="number">
                <button class="submitBtn bambooBtn" data-input="1">Continue</button>
              </div>
            </div>
          </div>
    
          <div class=".pledge-edition">
            <div class="pledge">
              <section class="pledgeThree"></section>
              <div>
                <h2>Black Edition Stand</h2>
                <a href="#">Pledge $75 or more</a>
                <div>
                  <h2>64</h2>
                  <div>left</div>
                </div>
              </div>
            </div>
    
            <p>
              You get a Black Special Edition computer stand and a personal thank you. You’ll be added to our Backer
              member list. Shipping is included.
            </p>
    
            <div class="pledge-amount">
              <p>Enter your pledge</p>
              <div>
                <input class="inputElement bambooInputElement" data-input="2" placeholder="$75" min="75" type="number">
                <button class="submitBtn blackEditionBtn" data-input="2" placeholder="$75" min="75">Continue</button>
              </div>
            </div>
          </div>
    

    输入值时的 HTML

    <div class="backed">
       <h1 class="backed-users">0</h1>
    </div>
    
    <div class="backers">
      <h1 class="number-of-backers">0</h1>
    </div>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-28
      • 1970-01-01
      • 2021-11-22
      • 2014-10-26
      • 1970-01-01
      • 2020-03-01
      相关资源
      最近更新 更多