通过DOM动态删除多个节点报错原因理解
在DOM中,我们可以通过removeChild( )来删除元素的子节点,但有时当我们通过循环函数删除一个元素的多个子节点时,浏览器却显示:
Failed to execute 'removeChild' on 'Node': parameter 1 is not of type 'Node'.
这是什么原因呢?接下来分析几个可能常出现的错误写法.
<ul id = "UL">
<li><input type="text"></li>
</ul>
<button id = "btn">添加</button>
<button id = "delete">DELETE</button>
<script>
var ul = document.getElementById("UL");
var btn = document.getElementById("btn");
var Delete = document.getElementById("delete");
btn.onclick = function(event)
{
var li = document.createElement("li");
var input = document.createElement("input");
li.appendChild(input);
ul.appendChild(li);
}
Delete.onclick = function(event)
{
//var count = ul.children.length;
//for(var i = 1;i<count;i++)
// ul.removeChild(ul.children[i]);
}
</script>
我们写个简单的程序,

当我们点击 添加 按钮时,会动态添加一个新的 < li > 元素,当点击删除按钮时,会删除出第一个< li >元素外所有的< li >元素。
Delete.onclick = function(event)
{
for(var i = 1;i<ul.children.length;i++)
ul.removeChild(ul.children[i]);
}
通过这种写法删除添加的子节点。结果是:


并没有完全删除,但浏览器没有报错
Delete.onclick = function(event)
{
var count = ul.children.length;
for(var i = 1;i<count;i++)
ul.removeChild(ul.children[i]);
}
通过这种方式,不仅删除不完全,浏览器还会报错。

- 正确方式 (方法不止一个)
Delete.onclick = function(event)
{
while(ul.children.length>=2)
ul.removeChild(ul.lastElementChild);
}
当时用这种方式时,浏览器没有报错而且达成我们的要求,即完全删除所有动态添加的子节点。


前两种方法错误的原因我觉得只有一点:对DOM理解不深。
依次分析代码
我们在循环函数判断条件那里写的是 ul.children.length ,即ul元素的子元素节点个数。 每当判断 i 的大小与 ul.children.length 的大小关系时,ul.children.length 都会发生一次更新。也就是说,ul.children.length 一直是动态变化的,当你添加一个子节点之后,他会动态加一,当你删除一个子节点时,他会动态减一。因此每当循环一次,ul.children.length的值就会减一。因此,当 i 的值大于等于 ul.children.length的值时,循环就停了。至于删除不完全是因为,每次删除后,ul.children[ i ] 的值就变成了删除前的ul.children[ i + 1 ], 可以简单理解为 ” 补位“, 前面一个走了,原来它后面的就占了它的位子。
Delete.onclick = function(event)
{
// while(ul.children.length>=2)
// ul.removeChild(ul.lastElementChild);
var count = ul.children.length;
for(var i = 1;i<count;i++)
{
ul.removeChild(ul.children[i]);
console.log(ul.children[i]);
}
}

打印出来ul的每个子节点,我们会发现控制台打印出来的结果中有一个 undefined 。原因和上面差不多,因为ul.children的长度是动态变化的,而count 记录的是初始时ul的子节点数,但随着ul子节点数量的减少以及 i 的增大,ul.children[i]会发生越界,因此打印出来的结果是undefined. 而removeChild()参数必须是一个节点才可以,否则会报错。
我觉得出现这样的错误是因为可能把ul.children当成静态数组了。如果我们删除数组中的元素,用这种方法完全没问题,但是这里的ul.children是动态的,因此要多加注意。
网友评论