如何通过创建元素将数据存入LocalStorage并展示?存值失败求助
问题原因
你用innerHTML存储内容时,input的实时输入值不会被包含在内。因为innerHTML获取的是元素的静态HTML结构,input的value是DOM的动态属性,修改后不会自动同步到innerHTML字符串里——你看到的input显示值是DOM的value属性,但innerHTML里的input标签仍保留最初创建时的状态,不会更新为最新输入值。
解决方案
不要存HTML结构,而是存数据本身。把每一条收入项的名称和金额存在数组中,将数组转成JSON字符串存入localStorage。页面加载时读取这个JSON,重新渲染所有收入项;添加新项时,先更新数据数组,再同步到localStorage,最后渲染DOM。
修改后的代码示例
// 初始化收入数据,优先从localStorage读取 let incomeData = JSON.parse(localStorage.getItem('incomeData')) || []; let incomeContainer = document.querySelector('#inc'); let incomeTotal = document.querySelector('#incomeTotal'); // 假设你有这个总金额元素 // 计算初始总金额 let incCounter = incomeData.reduce((sum, item) => sum + parseFloat(item.amount), 0); // 页面加载时先渲染已有数据 renderIncomeItems(); function userInput() { addInfo.forEach(btn => { btn.addEventListener('click', (e) => { let data = e.currentTarget.dataset.add; if (data === "income") { addIncome(); netWorth(); }; }) }) } function addIncome() { const incomeName = document.querySelector('#incomeName'); // 假设你有这个输入框 const incomeAmount = document.querySelector('#incomeAmount'); // 假设你有这个输入框 if (incomeName.value.trim() !== "" && incomeAmount.value.trim() !== "") { // 创建新的数据项 const newItem = { name: incomeName.value.trim(), amount: incomeAmount.value.trim() }; // 更新数据数组 incomeData.push(newItem); // 同步到localStorage localStorage.setItem('incomeData', JSON.stringify(incomeData)); // 更新总金额 incCounter += parseFloat(newItem.amount); updateIncomeTotal(); // 清空输入框 incomeName.value = ""; incomeAmount.value = ""; // 重新渲染所有收入项 renderIncomeItems(); } else { alert("Missing Income Info!"); } } // 根据数据渲染所有收入项 function renderIncomeItems() { // 先清空容器 incomeContainer.innerHTML = ''; incomeData.forEach(item => { let trackedDiv = document.createElement('div'); let inputName = document.createElement('input'); let inputAmount = document.createElement('input'); let btnDiv = document.createElement('div'); let editBtn = document.createElement('button'); let checkBtn = document.createElement('button'); let deleteBtn = document.createElement('button'); trackedDiv.classList.add('tracked'); inputName.classList.add('track_name'); inputName.type = "text"; inputAmount.classList.add('track_amount'); inputAmount.type = "number"; btnDiv.classList.add('btn_div'); editBtn.classList.add('edit_item'); checkBtn.classList.add('check_item'); deleteBtn.classList.add('delete_item'); editBtn.innerHTML = `<i class="fa-solid fa-pen-to-square"></i>`; checkBtn.innerHTML = `<i class="fa-solid fa-check"></i>`; deleteBtn.innerHTML = `<i class="fa-solid fa-trash"></i>`; inputName.disabled = "disabled"; inputAmount.disabled = "disabled"; // 从数据项赋值输入框内容 inputName.value = item.name; inputAmount.value = item.amount; // 添加删除功能(可选) deleteBtn.addEventListener('click', () => { incomeData = incomeData.filter(i => i !== item); incCounter -= parseFloat(item.amount); updateIncomeTotal(); localStorage.setItem('incomeData', JSON.stringify(incomeData)); renderIncomeItems(); }); // 组装DOM并添加到容器 trackedDiv.appendChild(inputName); trackedDiv.appendChild(inputAmount); btnDiv.appendChild(editBtn); btnDiv.appendChild(checkBtn); btnDiv.appendChild(deleteBtn); trackedDiv.appendChild(btnDiv); incomeContainer.appendChild(trackedDiv); }); } // 更新总金额显示 function updateIncomeTotal() { let convertedIncome = new Intl.NumberFormat('en-US', { style: "currency", currency: "USD", minimumFractionDigits: 0, maximumFractionDigits: 2 }).format(incCounter); incomeTotal.innerText = convertedIncome; }
补充说明
- 这种数据与DOM分离的方式,能彻底避免innerHTML的局限性,后续修改、删除、编辑功能都可以通过操作数据数组实现,再同步到存储并重新渲染。
- 如果需要支持编辑功能,只需修改对应数据项的内容,再同步到localStorage并调用
renderIncomeItems()即可。
内容的提问来源于stack exchange,提问作者iBuzz
相关产品推荐
相关产品推荐

