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

JS创建保存<tr>元素问题:仅第一条表格数据可存储求解决方案

财务工具记录保存问题解决建议

问题概述

我是编程新手,尤其不熟悉JavaScript。正在开发一个财务计算工具,功能是接收输入值计算后,将带日期的结果存入表格,要求每次新增输入都添加一条记录,页面刷新时能保存并取回所有数据。但目前只有第一条记录能被保存,求解决办法。

问题根源

  1. LocalStorage存储逻辑错误:当前用单个键存储单条记录的日期和金额,每次保存都会覆盖之前的数据,无法累积多条记录。
  2. 重复ID问题:新增表格行时重复使用id="date"和id="amount",导致获取数据时永远只能拿到第一条记录的内容。
  3. 事件嵌套绑定:save和done的事件监听嵌套在log点击事件内,每次点击log都会重复绑定事件,引发逻辑混乱。
  4. 日期生成时机错误:页面加载时就初始化了date变量,后续新增记录都会使用同一个日期,无法生成每次操作的实时日期。

解决代码及步骤

核心修改点

  • 改用数组存储所有记录,通过JSON.stringify和JSON.parse在LocalStorage中存取数组。
  • 移除重复ID,直接从新增的DOM元素中获取数据。
  • 将事件监听移到全局,避免重复绑定。
  • 每次生成记录时创建新的Date对象。

修改后的完整JavaScript代码

// 变量
const input = document.getElementById('input');

// 按钮
const enter = document.getElementById('enter-value');
const log = document.getElementById("log-value");
const save = document.getElementById("save-value");
const done = document.getElementById("done-button");

// 日志区域
const itemHolder = document.getElementById('item-holder');
const totalMarker = document.getElementById("grand-total");

// 提示信息
const negativeValueMessage = document.getElementById('value-message-negative');
const positiveValueMessage = document.getElementById('value-message-positive');
const doneMessage = document.getElementById("done");

// 其他
const tool = document.getElementById('tool');

// 输入验证
function checkInput() {
    input.addEventListener('input', function() {
        if (input.value < 0) {
            negativeValueMessage.style.display = "block";
            positiveValueMessage.style.display = "none";
            enter.style.display = "block";
            enter.disabled = false;
            enter.style.opacity = "100%";
        } else if (input.value > 0) {
            negativeValueMessage.style.display = "none";
            positiveValueMessage.style.display = "block";
            enter.style.display = "block";
            enter.disabled = false;
            enter.style.opacity = "100%";
        } else {
            negativeValueMessage.style.display = "none";
            positiveValueMessage.style.display = "none";
            enter.disabled = true;
            enter.style.opacity = '60%';
        }
    });
}
checkInput();

// 输入接收逻辑
function useInput() {
    let currentRecord = null; // 暂存当前要保存的记录

    enter.addEventListener('click', function() {
        enter.style.display = 'none';
        log.style.display = 'block';
        inputDisalowed();
    });

    log.addEventListener('click', function() {
        const addValues = Number(input.value) + Number(totalMarker.value || 0);
        totalMarker.value = addValues;
        // 生成当前操作的日期
        const date = new Date();
        const dateHolder = monthFixedValue(date) + '/' + date.getDate() + '/' + date.getFullYear();
        // 创建新行元素,避免重复ID
        const newRow = document.createElement('tr');
        newRow.innerHTML = `<td>${dateHolder}</td><td>$${totalMarker.value}</td>`;
        itemHolder.appendChild(newRow);
        // 暂存当前记录
        currentRecord = { date: dateHolder, amount: `$${totalMarker.value}`, total: addValues };
        
        log.style.display = 'none';
        save.style.display = 'block';
    });

    save.addEventListener('click', function() {
        doneMessage.style.display = "grid";
        tool.style.display = 'none';
        // 获取已存的记录数组,没有则初始化空数组
        let records = JSON.parse(localStorage.getItem('financeRecords')) || [];
        // 添加当前记录
        records.push(currentRecord);
        // 存回LocalStorage
        localStorage.setItem('financeRecords', JSON.stringify(records));
        // 更新总金额
        localStorage.setItem('savedTotal', currentRecord.total);
    });

    done.addEventListener('click', function() {
        reloadPage();
    });
}
useInput();
retrieveOnReload();

// 补全月份为两位(可选优化)
function monthFixedValue(date) {
    const month = date.getMonth() + 1;
    return month < 10 ? `0${month}` : month;
}

function inputDisalowed() {
    input.addEventListener('input', function() {
        alert("您已输入过数值,再次输入会重置流程。");
        location.reload();
    });
}

// 页面加载时取回所有记录
function retrieveOnReload() {
    window.addEventListener('DOMContentLoaded', function() {
        const records = JSON.parse(localStorage.getItem('financeRecords')) || [];
        // 遍历所有记录添加到表格
        records.forEach(record => {
            const newRow = document.createElement('tr');
            newRow.innerHTML = `<td>${record.date}</td><td>${record.amount}</td>`;
            itemHolder.appendChild(newRow);
        });
        // 设置总金额
        totalMarker.value = localStorage.getItem('savedTotal') || 0;
    });
}

function reloadPage() {
    window.location.href = window.location.href;
}

额外优化说明

  • 补全了月份为两位数字的逻辑(如1月显示为01),让日期格式更规范。
  • 初始化总金额时添加了|| 0,避免首次加载时出现NaN。
  • 使用document.createElement和appendChild替代innerHTML +=,性能更优且避免XSS风险。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 04:49:50