防止同时单击具有相同 class 的按钮
Prevent buttons with same class from being clicked simultaneously
我有两个具有相同 class 名称和相同功能但必须添加不同输入的按钮,因此我使用了 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 .');
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);
})
实际上并不是同时“单击”两个按钮。发生的情况如下:
您的 calculateBamboo()
函数循环遍历所有 inputElements:inputElements.forEach()
;并且您正在为所有输入执行您的逻辑。因此,无论您按哪个按钮,calculateBamboo()
都在处理 每个 输入。
使用数据属性传递目标输入将帮助您识别哪个输入属于点击的按钮
此外,@JerryBen 是对的,您不需要为每个按钮添加事件监听器,而是我们可以 wrap 一个元素中的所有按钮,添加事件监听器并确定点击了哪个元素。
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 .');
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 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="" 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 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="" min="75" type="number">
<button class="submitBtn blackEditionBtn" data-input="2" placeholder="" min="75">Continue</button>
</div>
</div>
</div>
</div>
向每个按钮添加事件侦听器被认为是一种不好的做法。相反,使用单个事件侦听器来统治它们:
- 将按钮包装在 div 元素中
- 仅向 div 包装器添加点击事件
- 将
event
对象作为参数传递给处理函数
- 事件处理函数将使用
event.target
来识别单击了哪个特定按钮:
function calculateBamboo(evt){ const inputValue = parseFloat(evt.target.value) }
希望对您有所帮助
我现在的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 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="" 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 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="" min="75" type="number">
<button class="submitBtn blackEditionBtn" data-input="2" placeholder="" 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>
我有两个具有相同 class 名称和相同功能但必须添加不同输入的按钮,因此我使用了 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 .');
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);
})
实际上并不是同时“单击”两个按钮。发生的情况如下:
您的 calculateBamboo()
函数循环遍历所有 inputElements:inputElements.forEach()
;并且您正在为所有输入执行您的逻辑。因此,无论您按哪个按钮,calculateBamboo()
都在处理 每个 输入。
使用数据属性传递目标输入将帮助您识别哪个输入属于点击的按钮
此外,@JerryBen 是对的,您不需要为每个按钮添加事件监听器,而是我们可以 wrap 一个元素中的所有按钮,添加事件监听器并确定点击了哪个元素。
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 .');
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 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="" 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 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="" min="75" type="number">
<button class="submitBtn blackEditionBtn" data-input="2" placeholder="" min="75">Continue</button>
</div>
</div>
</div>
</div>
向每个按钮添加事件侦听器被认为是一种不好的做法。相反,使用单个事件侦听器来统治它们:
- 将按钮包装在 div 元素中
- 仅向 div 包装器添加点击事件
- 将
event
对象作为参数传递给处理函数 - 事件处理函数将使用
event.target
来识别单击了哪个特定按钮:
function calculateBamboo(evt){ const inputValue = parseFloat(evt.target.value) }
希望对您有所帮助
我现在的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 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="" 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 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="" min="75" type="number">
<button class="submitBtn blackEditionBtn" data-input="2" placeholder="" 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>