解决removeChild报错:参数非Node类型及删除功能失效问题
解决
TypeError: failed to execute 'removeChild' on 'Node' 问题 这个报错的核心原因很明确:你调用txtTabell.removeChild(tr)时,tr并不是一个有效的DOM节点(大概率是null)。咱们一步步拆解问题:
1. 最直接的问题:删除按钮的传参错误
看你加载内容函数里的这段代码:
onclick="slett('${pk},${pkk}')"
你这里把pk和pkk拼成了一个字符串(比如"123,456")传给slett函数,但你的slett函数只接收一个参数pk。这就导致:
- 函数里的
pk实际是"123,456" - 然后
document.getElementById(${pk})会去查找id为"123,456"的tr,但你的tr的id是单独的pk(比如123),自然找不到,返回null - 最后调用
removeChild(null)就触发了你看到的报错
修复方案:修正传参方式
把传参改成两个独立的参数:
onclick="slett('${pk}', '${pkk}')"
然后修改slett函数,接收两个参数,分别处理对应的删除逻辑:
function slett(pk, pkk) { // 删除数据库中的arrangement数据 var sletttime = arrangement.child(pk); sletttime.remove(); // 删除数据库中的russ数据(复用你之前的fjern逻辑) var slettruss = russ.child(pkk); slettruss.remove(); // 删除表格中的对应行,先判断节点是否存在 var tr = document.getElementById(pk); if (tr) { txtTabell.removeChild(tr); } }
这样就能正确获取到对应的tr节点了。
2. 额外的潜在问题:重复添加DOM节点
你的hentArrangement函数里用了txtTabell.innerHTML += ...,如果这个函数被多次调用(比如实时监听数据变化时),会重复添加相同的tr,导致页面出现多个id相同的元素。DOM中id必须唯一,这会导致getElementById只能找到第一个匹配的元素,后续的删除操作会失效。
优化建议:
每次加载数据前先清空原有内容,避免重复添加:
function hentArrangement(snapshot){ // 先清空表格内容,避免重复渲染 txtTabell.innerHTML = ''; txtTabell2.innerHTML = ''; // 遍历snapshot中的子节点(实时监听时必须用forEach) snapshot.forEach(function(childSnapshot) { var pk = childSnapshot.key; var nyTime = childSnapshot.val(); var russRef = database.ref("russ/" + nyTime.russ); russRef.on("value", function(snapshotruss){ var pkk = snapshotruss.key; var russObj = snapshotruss.val(); txtTabell.innerHTML += ` <tr id="${pk}"> <td><label class="russlabel" onclick="edit('${pk}')">${nyTime.arrangør}</label><input type="text" class="editItem" style="display:none"></td> <td>${nyTime.adresse}</td> <td>${nyTime.postadresse}</td> <td>${nyTime.poststed}</td> <td>${nyTime.pris}</td> <td>${russObj.navn}</td> <td>${russObj.russadresse}</td> <td>${russObj.mobilnr}</td> <td>${russObj.kjonn}</td> </tr>`; // 修复tr标签的id写法错误:<tr =${pkk}> → <tr id="${pkk}"> txtTabell2.innerHTML +=` <tr id="${pkk}"> <td>${russObj.navn}</td> <td>${russObj.russadresse}</td> <td>${russObj.mobilnr}</td> <td>${russObj.kjonn}</td> <td><label class="delete" onclick="slett('${pk}', '${pkk}')"><button>Slett</button></label></td> </tr>`; }); }); }
另外注意你在txtTabell2里的tr标签写错了:<tr =${pkk}>应该改成<tr id="${pkk}">,否则这个tr也没有正确的id标识。
3. 最后:添加节点存在性判断
在删除DOM节点前,先判断节点是否存在且属于目标父节点,即使后续有意外情况,也不会抛出报错:
var tr = document.getElementById(pk); if (tr && tr.parentNode === txtTabell) { txtTabell.removeChild(tr); }
按照上面的步骤修改后,你的删除功能应该就能恢复正常了。
内容的提问来源于stack exchange,提问作者Raahim Khan




