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

JS预算计算器删除功能故障:无法更新newMoneyArr与可用余额

修复预算计算器的transactionDelete函数

我正在开发一款JS预算计算器应用,已完成部分功能,但卡在transactionDelete函数上。该函数需要实现从收入/支出区域删除交易记录,同时更新moneyArr并在可用余额中显示最新数值。


原代码

JavaScript

const incomeSection = document.querySelector(".income-area");
const expensesSection = document.querySelector(".expenses-area");
const availableMoney = document.querySelector(".available-money");
const addTransactionPanel = document.querySelector(".add-transaction-panel");

const nameInput = document.querySelector("#name");
const amountInput = document.querySelector("#amount");
const categorySelect = document.querySelector("#category");
const errorTransactionname = document.querySelector(".error-transaction-name");
const errorTransactionAmount = document.querySelector(
  ".error-transaction-amount"
);
const errorTransactionOption = document.querySelector(
  ".error-transaction-option"
);
const errorMsg = document.querySelector(".error-msg");

const addTransactionBtn = document.querySelector(".add-transaction");
const saveBtn = document.querySelector(".save");
const cancelBtn = document.querySelector(".cancel");
const deleteAllBtn = document.querySelector(".delete-all");


let ID = 0;
let newMoneyArr
let moneyArr = []


const checkTransactionName = () => {
  if (nameInput.value.length == 0) {
    errorTransactionname.style.display = "block";
    errorTransactionname.innerHTML = "Transaction name cannot be empty!";
  } else if (nameInput.value.length > 10) {
    errorTransactionname.style.display = "block";
    errorTransactionname.innerHTML =
      "Transaction name cannot be longer then 10 charcters";
  } else {
    errorTransactionname.innerHTML = "";
  }
};

const checkTransactionAmount = () => {
  if (amountInput.value.length == 0) {
    errorTransactionAmount.style.display = "block";
    errorTransactionAmount.innerHTML = "Transaction amount cannot be empty!";
  } else if (amountInput.value.length >= 6) {
    errorTransactionAmount.style.display = "block";
    errorTransactionAmount.innerHTML =
      "Transaction amount cannot be longer then 5 digits";
  } else {
    errorTransactionAmount.innerHTML = "";
  }
};

const checkSelect = () => {
  if (categorySelect.selectedIndex == 0) {
    errorTransactionOption.style.display = "block";
    errorTransactionOption.innerHTML = "Choose one of the two options";
  } else {
    errorTransactionOption.innerHTML = "";
  }
};

const createTransaction = () => {
  checkTransactionName();
  checkTransactionAmount();
  checkSelect();

  if (
    errorTransactionAmount.innerHTML != "" ||
    errorTransactionAmount.innerHTML != "" ||
    errorTransactionOption.innerHTML != ""
  ) {
    errorMsg.style.display = "block";
    errorMsg.innerHTML = "Fill out all the spaces correctly please";
  } else {
    let newTransaction = document.createElement("li");
    newTransaction.setAttribute("id", ID);
    newTransaction.classList.add("transaction");
    newTransaction.innerHTML = `<p class="transaction-name">${nameInput.value}</p>
                                    <p class="transaction-amount">${amountInput.value}zł
                                    <button onclick = 'transactionDelete(${ID})' class="delete">
                                    <i class="fas fa-times"></i></button></p>`;

    if (categorySelect.selectedIndex == 1) {
      incomeSection.appendChild(newTransaction);
      newTransaction.classList.add("income-transaction");
    } else {
      expensesSection.appendChild(newTransaction);
      newTransaction.classList.add("expense-transaction");
    }

    ID++;
    newBalance();
    closePanel();
  }
};

const newBalance = () => {
  if (categorySelect.selectedIndex == 1) {
    moneyArr.push(parseFloat(amountInput.value));
  } else {
    let newAmount2 = parseFloat(amountInput.value);
    let newAmount = -newAmount2;
    moneyArr.push(newAmount);
  }

  let newMoneyArr = moneyArr.reduce((a, b) => {
    return a + b;
  });
};


const clearInputs = () => {
  nameInput.value = "";
  amountInput.value = "";
  categorySelect.selectedIndex = 0;
  errorTransactionname.innerHTML = "";
  errorTransactionAmount.innerHTML = "";
  errorTransactionOption.innerHTML = "";
  errorMsg.innerHTML = "";
};

saveBtn.addEventListener("click", createTransaction);

addTransactionBtn.addEventListener(
  "click",
  (showPanel = () => {
    addTransactionPanel.style.display = "flex";
  })
);

cancelBtn.addEventListener(
  "click",
  (closePanel = () => {
    addTransactionPanel.style.display = "none";
    clearInputs();
  })
);

const deleteAllTransactions = () => {
  incomeSection.innerHTML = "<h3>Income</h3>";
  expensesSection.innerHTML = "<h3>Expenses</h3>";
  availableMoney.textContent = "0$";
  moneyArr = [0];
};

deleteAllBtn.addEventListener("click", deleteAllTransactions);

// 待完善的函数
transactionDelete = (id) => {
  const transactionToDelete = document.getElementById(id);
  const transactionAmount = parseFloat(transactionToDelete.childNodes[2].innerText);

  if (transactionToDelete.classList.contains('income-transaction')) {
    incomeSection.removeChild(transactionToDelete);
  } else {
    expensesSection.removeChild(transactionToDelete);
  }
};

HTML

<link href="https://fonts.googleapis.com/css?family=Montserrat:200,400,700&display=swap&subset=latin-ext" rel="stylesheet">

<link rel="stylesheet" href="style.css">
<script src="https://kit.fontawesome.com/6c5198f753.js" crossorigin="anonymous"></script>

<header>
  <h1><i class="fas fa-wallet"></i> Wallet</h1>
  <p>Finance manager</p>
</header>

<main>
  <div class="transactions-wrapper">
    <section class="transactions">
      <h2 class="title">Transaction list</h2>
      <div class="transaction-list">
        <div class="income-area">
          <h3>Income</h3>
        </div>
        <div class="expenses-area">
          <h3>Expenses</h3>
        </div>
      </div>
    </section>
  </div>

  <section class="options">
    <div>
      <h2 class="title">Available money:</h2>
      <p class="available-money">0$</p>
    </div>
    <div class="controls">
      <button class="add-transaction"><i class="fas fa-plus"></i> add transaction</button>
      <button class="delete-all"><i class="far fa-trash-alt"></i> delete everything</button>
    </div>
  </section>
</main>
<div class="add-transaction-panel">
  <div class="panel-wrapper">
    <h2 class="title">add new transaction</h2>

    <div class="form-box">
      <label for="name">name:</label>
      <input type="text" id="name">
      <p class="error-transaction-name"></p>
    </div>

    <div class="form-box">
      <label for="amount">amount:</label>
      <input type="number" id="amount">
      <p class="error-transaction-amount"></p>
    </div>

    <div class="form-box">
      <label for="category">select category:</label>
      <select id="category">
        <option value="none" selected>chose if the transaction is a income or expense</option>
        <option value="income">income</option>
        <option value="shopping">expense</option>
      </select>
      <p class="error-transaction-option"></p>
    </div>
    <p class="error-msg"></p>
    <div class="panel-buttons">
      <button class="save" type="button"><i class="fas fa-save"></i> save</button>
      <button class="cancel" type="button"><i class="far fa-window-close"></i> cancel</button>
    </div>
  </div>
</div>

解决方案

要完成删除功能,需解决三个核心问题:正确提取金额、同步更新数据数组、刷新页面余额显示,同时修复原代码的逻辑漏洞。

1. 重构newBalance函数,适配后续删除逻辑

将moneyArr改为存储带ID的对象,方便删除时精准匹配,同时补全页面余额更新逻辑:

const newBalance = () => {
  // 初始化空数组(避免全删后残留0值)
  if (moneyArr.length === 0 || moneyArr[0] === 0) {
    moneyArr = [];
  }
  
  // 存储带ID的交易数据
  if (categorySelect.selectedIndex === 1) {
    moneyArr.push({ id: ID, amount: parseFloat(amountInput.value) });
  } else {
    moneyArr.push({ id: ID, amount: -parseFloat(amountInput.value) });
  }

  // 计算总余额并更新页面
  const total = moneyArr.reduce((sum, item) => sum + item.amount, 0);
  availableMoney.textContent = `${total.toFixed(2)}zł`;
};

2. 完善transactionDelete函数

处理金额提取、DOM移除、数组更新和余额刷新:

transactionDelete = (id) => {
  const transactionToDelete = document.getElementById(id);
  // 提取金额:移除zł符号后转数字
  const amountText = transactionToDelete.querySelector('.transaction-amount').textContent;
  const transactionAmount = parseFloat(amountText.replace('zł', '').trim());

  // 从DOM中移除交易项
  if (transactionToDelete.classList.contains('income-transaction')) {
    incomeSection.removeChild(transactionToDelete);
  } else {
    expensesSection.removeChild(transactionToDelete);
  }

  // 从数据数组中移除对应项
  moneyArr = moneyArr.filter(item => item.id !== id);

  // 重新计算并更新余额
  const total = moneyArr.reduce((sum, item) => sum + item.amount, 0);
  availableMoney.textContent = `${total.toFixed(2)}zł`;
};

3. 同步修复deleteAllTransactions函数

适配新的数据结构,确保全删后数据和页面一致:

const deleteAllTransactions = () => {
  incomeSection.innerHTML = "<h3>Income</h3>";
  expensesSection.innerHTML = "<h3>Expenses</h3>";
  availableMoney.textContent = "0zł";
  moneyArr = [];
};

内容的提问来源于stack exchange,提问作者Marcelo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 16:07:15