JavaScript 费用跟踪器计算器 - 减法

JavaScript Expense Tracker Calculator - Subtraction

我正在尝试使用 vanilla javascript 做一个费用跟踪器,用户可以 add/remove 他们的费用项目,费用总额将相应计算。

我正在使用构造函数创建对象,以便稍后我可以保存在 localStorage 中并稍后检索(这部分还没有完成)

问题来了。添加atm没有问题,但是在删除项目时(如果不是按顺序删除),计算就乱了。例如。 Item 1,Item 2,Item 3。如果我用订单移除 Item 3 --> Item2 --> Item 减去总值没有问题。但是如果从Item 1或者Item 2开始移除,计算就会乱

我不确定是不是因为每个项目中都没有 index/id,所以计算不起作用。感谢您的帮助,谢谢!

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="ExpenseTracker.css">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css">
    
    <script src="https://cdn.jsdelivr.net/npm/flatpickr"></script>
    
    <title>Document</title>
</head>
<body>
    <div class="container">
        <label name="expense">Expense: </label>
        <input id="inputField" name="expense" type="text">
        <label name="date">Date: </label>
        <input id="start" type="text" name="date">
        <label name="amount">Amount: </label>
        <input id="money" name="amount" type="number" min="0" step="0.1">
        <button id="add" >Add</button>
        <table>
            <thead>
                <tr style="border: 1px solid black;">
                    <th>Description</th>
                    <th>Date</th>
                    <th>Amount</th>
                </tr>
            </thead>
            <tbody id="listContainer" style="border: 1px solid black;">
                
            </tbody>
            <tr>
                <td id="total">total</td>
            </tr>
        </table>
        
        <button onclick="clearHistory()">clear localStorage</button>
    </div>



    
    <script>
        class ExpenseObject{
        
        constructor(e, d, a){
          
          this.expenseDescription = e;
          this.dateObject = d;
          this.amount = a;
        }
      }
        function clearHistory(){
            localStorage.clear();
        }
        const createDate = flatpickr("#start",{
            dateFormat:"d-m-Y ",
        });

        let addButton = document.getElementById("add");
        let listContainer=document.getElementById("listContainer");
        let inputField= document.getElementById("inputField");
        let dateInput = document.getElementById("start");
        let amountField = document.getElementById("money");
        let total = document.getElementById("total");

        

        addButton.addEventListener('click', function(){
            if(!inputField.value || !dateInput.value || !amountField.value){
                alert("please do not leave blank in any field");
                return;
            }

            var newRow = document.createElement('tr');
            var expense = document.createElement('td');
            var expenseDate = document.createElement('td');
            var expenseAmount = document.createElement('td');
            var deleteButton = document.createElement('button');
        
            
            deleteButton.innerHTML="X";

            let expenseStuff = new ExpenseObject (inputField.value,dateInput.value,amountField.value )
           
            expense.innerHTML = expenseStuff.expenseDescription; 
            expenseDate.innerHTML =  expenseStuff.dateObject;
            expenseAmount.innerText = expenseStuff.amount;
            listContainer.appendChild(newRow);
            newRow.appendChild(expense);
            newRow.appendChild(expenseDate);
            newRow.appendChild(expenseAmount);
            newRow.appendChild(deleteButton);
           
            
            inputField.value = "";
            amountField.value="";
            
            
            var totalAmount = parseFloat(total.innerText) || 0;
            totalAmount += parseFloat(expenseAmount.innerHTML);
            total.innerHTML = totalAmount;
           
            
            deleteButton.addEventListener('click', function(){
                newRow.removeChild(expense);
                newRow.removeChild(expenseDate);
                newRow.removeChild(expenseAmount);
                newRow.removeChild(deleteButton);
                totalAmount -= parseFloat(expenseAmount.innerHTML);
                total.innerHTML = totalAmount;
            })
        })

    </script>
</body>
</html>

您遇到的主要问题是您在本地范围内声明了 totalAmount,因此每个 deleteButton 事件监听器仍然引用监听器声明时的旧 totalAmount 值.如果您在更高级别的范围内声明该值,连同 total,一切都会按预期工作。

这是实际操作:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="ExpenseTracker.css">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css">
    <script src="https://cdn.jsdelivr.net/npm/flatpickr"></script>
    <title>Document</title>
</head>
<body>
    <div class="container">
        <label name="expense">Expense: </label>
        <input id="inputField" name="expense" type="text">
        <label name="date">Date: </label>
        <input id="start" type="text" name="date">
        <label name="amount">Amount: </label>
        <input id="money" name="amount" type="number" min="0" step="0.1">
        <button id="add" >Add</button>
        <table>
            <thead>
                <tr style="border: 1px solid black;">
                    <th>Description</th>
                    <th>Date</th>
                    <th>Amount</th>
                </tr>
            </thead>
            <tbody id="listContainer" style="border: 1px solid black;">
            </tbody>
            <tr>
                <td id="total">total</td>
            </tr>
        </table>
        <button onclick="clearHistory()">clear localStorage</button>
    </div>
    <script>
        class ExpenseObject{
          constructor(e, d, a){
            this.expenseDescription = e;
            this.dateObject = d;
            this.amount = a;
          }
        }
        function clearHistory(){
            localStorage.clear();
        }
        const createDate = flatpickr("#start",{
            dateFormat:"d-m-Y ",
        });
        let addButton = document.getElementById("add");
        let listContainer = document.getElementById("listContainer");
        let inputField = document.getElementById("inputField");
        let dateInput = document.getElementById("start");
        let amountField = document.getElementById("money");
        let total = document.getElementById("total");
        let totalAmount = parseFloat(total.innerText) || 0;
        addButton.addEventListener('click', function(){
            if(!inputField.value || !dateInput.value || !amountField.value){
                alert("please do not leave blank in any field");
                return;
            }
            const newRow = document.createElement('tr');
            const expense = document.createElement('td');
            const expenseDate = document.createElement('td');
            const expenseAmount = document.createElement('td');
            const deleteButton = document.createElement('button');
            deleteButton.innerHTML="X";
            let expenseStuff = new ExpenseObject (inputField.value,dateInput.value,amountField.value )
            expense.innerHTML = expenseStuff.expenseDescription;
            expenseDate.innerHTML =  expenseStuff.dateObject;
            expenseAmount.innerText = expenseStuff.amount;
            listContainer.appendChild(newRow);
            newRow.appendChild(expense);
            newRow.appendChild(expenseDate);
            newRow.appendChild(expenseAmount);
            newRow.appendChild(deleteButton);
            inputField.value = "";
            amountField.value = "";
            totalAmount += parseFloat(expenseAmount.innerHTML);
            total.innerHTML = totalAmount;
            deleteButton.addEventListener('click', function() {
                newRow.removeChild(expense);
                newRow.removeChild(expenseDate);
                newRow.removeChild(expenseAmount);
                newRow.removeChild(deleteButton);
                totalAmount -= parseFloat(expenseAmount.innerHTML);
                total.innerHTML = totalAmount;
            })
        })
    </script>
</body>
</html>