JavaScript DOM操作:如何同步删除JSON数据和对应的DOM元素
功能修复方案
核心问题
- 仅修改了内存中的数组数据,未关联删除对应的DOM节点,所以页面不会同步更新
- 直接用
idx-1作为数组下标删除逻辑有缺陷:当删除前面的条目后,后续条目的数组下标会发生变化,和userId不再匹配,会出现删错数据的问题 - 原有删除事件绑定的写法存在冗余,不需要额外传入event参数
具体修改步骤
1. 给DOM节点添加唯一标识
在createEle函数中给每个条目根节点添加自定义属性存储userId,方便后续删除时快速定位对应的DOM:
const createEle = (data, idx) => { let main = document.createElement("div"); // 新增:存储当前条目的userId,DOM上会生成data-userid属性 main.dataset.userId = data.userId; let container = document.getElementById("container"); let title = document.createElement('div'); let age = document.createElement('div'); let remove = document.createElement('div'); let update = document.createElement('div'); main.className = "main"; title.className = "title"; age.className = "age"; remove.className = "delete"; update.className = "update"; container.appendChild(main); main.appendChild(title); main.appendChild(age); main.appendChild(update); main.appendChild(remove); // 简化事件绑定,不需要用bind remove.addEventListener("click", () => deleteEle(data.userId)); title.append(data.name); age.append(data.age); update.append("Edit"); remove.append("Delete"); }
2. 优化删除逻辑,同步删除DOM和数据
修改deleteEle函数,先定位到对应DOM节点删除,再删除数组中的对应数据:
const deleteEle = (userId) => { // 第一步:删除对应DOM节点,注意dataset属性在选择器中为全小写短横线格式 const targetDom = document.querySelector(`.main[data-userid="${userId}"]`); targetDom && targetDom.remove(); // 第二步:按userId匹配删除数组数据,避免下标错位问题 const targetIndex = names.nameList.findIndex(item => item.userId === userId); if (targetIndex > -1) { names.nameList.splice(targetIndex, 1); } console.log("deleted", userId, names.nameList); }
3. 优化渲染逻辑
原渲染用的map方法是用于生成新数组的,纯遍历渲染建议改用forEach,更符合语义:
const displayData = () => { names.nameList.forEach(data => { createEle(data, data.userId); }); }
面向对象实现示例
如果想要改用面向对象写法,可以把所有数据和操作封装到同一个类中,逻辑更内聚,后续扩展功能也更方便:
class UserManager { constructor() { this.nameList = [ {userId: 1, name: "abc", age: "25"}, {userId: 2, name: "def", age: "23"}, {userId: 3, name: "ghi", age: "18"}, {userId: 4, name: "jkl", age: "19"}, ]; this.container = document.getElementById("container"); } #createUserItem(data) { const main = document.createElement("div"); main.dataset.userId = data.userId; main.className = "main"; const title = document.createElement('div'); title.className = "title"; title.append(data.name); const age = document.createElement('div'); age.className = "age"; age.append(data.age); const update = document.createElement('div'); update.className = "update"; update.append("Edit"); const remove = document.createElement('div'); remove.className = "delete"; remove.append("Delete"); remove.addEventListener("click", () => this.delete(data.userId)); main.append(title, age, update, remove); this.container.appendChild(main); } render() { // 渲染前清空容器,避免后续新增/修改数据时重复渲染 this.container.innerHTML = ''; this.nameList.forEach(item => this.#createUserItem(item)); } delete(userId) { // 删除DOM const targetDom = this.container.querySelector(`.main[data-userid="${userId}"]`); targetDom && targetDom.remove(); // 删除数据 const targetIndex = this.nameList.findIndex(item => item.userId === userId); targetIndex > -1 && this.nameList.splice(targetIndex, 1); } // 后续可以直接在类中扩展add、find等方法 find() { console.log("Find function"); } add(userInfo) { this.nameList.push(userInfo); this.render(); } } // 初始化使用 const userManager = new UserManager(); userManager.render();
内容的提问来源于stack exchange,提问作者Nandakumar singh
相关产品推荐
相关产品推荐

