如何在addEventListener中传递参数,使calculateBill获取所有事件值
如何让calculateBill获取所有事件触发时的参数值?
我的需求是:在所有addEventListener中捕获事件后调用calculateBill函数,希望每个事件监听能单独传递对应参数,但目前出现事件值丢失的问题。我知道可以用其他方式完成这个FrontendMentor挑战,但想搞清楚这种方式能不能实现。我确定问题出在addEventListener的参数调用上,请问怎么调整才能让calculateBill获取到所有需要的参数?
我的代码:
const billInput = document.querySelector('#bill'); const percentageButton = document.querySelectorAll('.tip__values--item'); const numberOfPeople = document.querySelector('#people'); const tipAmount = document.querySelector('.result__amount--price'); const totalBill = document.querySelector('.result__total--price'); const reset = document.querySelector('button'); const catchBill = (e) => { return e.target.value; }; const catchPeople = (e) => { return e.target.value; }; const handleButtons = (e) => { return e.target.textContent; }; const calculateBill = (catchBill, catchPeople, handleButtons) => { console.log( 'catchBill:', catchBill, 'catchPeople:', catchPeople, 'handleButtons:', handleButtons ); }; billInput.addEventListener('keyup', function (e) { calculateBill(catchBill(e), catchPeople, handleButtons); }); numberOfPeople.addEventListener('keyup', function (e) { calculateBill(catchBill, catchPeople(e), handleButtons); }); percentageButton.forEach((btn) => { btn.addEventListener('click', function (e) { calculateBill(catchBill, catchPeople, handleButtons(e)); }); });
问题原因
你现在的写法有个核心问题:每次触发事件时,只传递了当前事件对应的那个值,另外两个参数传的是函数本身,不是对应元素的当前值。比如在账单输入框的keyup事件里,catchBill(e)确实拿到了当前账单值,但catchPeople是函数对象、handleButtons也是函数对象,不是当前的人数和小费百分比,所以calculateBill里打印的自然不是你要的数值。
解决方法
不管哪个事件触发,调用calculateBill时都要主动获取三个值的最新状态,而不是只传当前事件对应的那个。可以这么调整:
- 新增变量存储当前选中的小费百分比,因为按钮点击后需要保留这个值,后续其他事件触发时也要用到
- 把获取账单、人数的逻辑改成直接读取元素当前值,不需要依赖事件参数
- 每个事件监听里,先更新对应状态(比如点击小费按钮时更新百分比),再把三个最新值传入
calculateBill
调整后的代码:
const billInput = document.querySelector('#bill'); const percentageButton = document.querySelectorAll('.tip__values--item'); const numberOfPeople = document.querySelector('#people'); const tipAmount = document.querySelector('.result__amount--price'); const totalBill = document.querySelector('.result__total--price'); const reset = document.querySelector('button'); // 存储当前选中的小费百分比,默认0 let selectedTipPercentage = 0; // 直接获取当前账单输入值,转成数字,空值默认0 const getCurrentBill = () => { return parseFloat(billInput.value) || 0; }; // 直接获取当前人数输入值,转成数字,空值/无效值默认1(避免除以0) const getCurrentPeople = () => { const people = parseFloat(numberOfPeople.value); return isNaN(people) || people <= 0 ? 1 : people; }; // 点击小费按钮时更新选中的百分比 const handleTipButtonClick = (e) => { // 去掉%符号并转成数字 selectedTipPercentage = parseFloat(e.target.textContent.replace('%', '')) || 0; }; const calculateBill = (bill, people, tipPercent) => { console.log('账单:', bill, '人数:', people, '小费百分比:', tipPercent); // 这里可以写计算逻辑了 const tipPerPerson = (bill * (tipPercent / 100)) / people; const totalPerPerson = (bill / people) + tipPerPerson; tipAmount.textContent = `$${tipPerPerson.toFixed(2)}`; totalBill.textContent = `$${totalPerPerson.toFixed(2)}`; }; // 账单输入框变化时,传三个最新值 billInput.addEventListener('keyup', function () { calculateBill(getCurrentBill(), getCurrentPeople(), selectedTipPercentage); }); // 人数输入框变化时,传三个最新值 numberOfPeople.addEventListener('keyup', function () { calculateBill(getCurrentBill(), getCurrentPeople(), selectedTipPercentage); }); // 小费按钮点击时,先更新百分比,再传三个最新值 percentageButton.forEach((btn) => { btn.addEventListener('click', function (e) { handleTipButtonClick(e); calculateBill(getCurrentBill(), getCurrentPeople(), selectedTipPercentage); }); });
说明
- 现在不管哪个事件触发,
calculateBill都能拿到账单、人数、小费百分比的最新值,不会出现值丢失的情况 - 加入了数值转换和容错处理,避免输入空值或非数字导致计算出错
- 这种写法完全符合你想要的“通过事件监听传递参数调用calculateBill”的思路
内容的提问来源于stack exchange,提问作者Wojtek1911
相关产品推荐
相关产品推荐

