You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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时都要主动获取三个值的最新状态,而不是只传当前事件对应的那个。可以这么调整:

  1. 新增变量存储当前选中的小费百分比,因为按钮点击后需要保留这个值,后续其他事件触发时也要用到
  2. 把获取账单、人数的逻辑改成直接读取元素当前值,不需要依赖事件参数
  3. 每个事件监听里,先更新对应状态(比如点击小费按钮时更新百分比),再把三个最新值传入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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 19:30:32