JS中使用appendChild()插入节点需要注意的事项

首先看下面一段代码:

    <div id="box">
        <p>参考的P标签元素</p>
    </div>
    <hr>
    <div id="target">
        <p>p text 1</p>
        <p>p text 2</p>
        <p>p text 3</p>
        <p>p text 4</p>
        <p>p text 5</p>
    </div>

    <script>
        var box = document.getElementById("box");
        var target = document.getElementById("target");

        var targetChildrens = target.children;
        for (var i = 0; i < targetChildrens.length; i++) {
            box.appendChild(targetChildrens[i]);
        }
    </script>

我们知道使用 appendChild() 给一个父节点插入子节点,这个方法插入的位置都是在父节点元素最后一个子元素之后插入的。
所以可以看出,这段代码的意图是想把 id 为 target 下的所有 p 标签元素追加到 id 为 box 中 p 标签的后面,但需要注意的是: 如果插入的子节点是DOM文档树里面已经存在的节点的话,这个节点会被移动到用appendChild() 插入的位置,而不会被复制。

如果想复制而不是移动追加,那么就需要使用 cloneNode() ,该方法将复制并返回调用它的节点的副本。语法如下:

node.cloneNode(deep);

其中
node: 被克隆节点
deep: 可选,默认为 false。如果传递给它的参数是 true,它还将递归复制当前节点的所有子孙节点。否则,它只复制当前节点,注意,只会复制到标签,而不会包括里面的文本内容

所以可以将代码段中的 box.appendChild(targetChildrens[i]) 改为如下,实现复制而不是移动追加:

box.appendChild( targetChildrens[i].cloneNode(true) );

对于动态生成(通过createElement创建)的节点,则可以直接使用 appendChild() 来追加。

    <div id="box">
        <p>参考的P标签元素</p>
    </div>

    <script>
        var box = document.getElementById("box");
        var target = document.getElementById("target");

        for(var i = 1; i <= 5; i++){
            var p = document.createElement("p");
            var textNode = document.createTextNode('动态添加的p标签' + i);
            p.appendChild(textNode);
            box.appendChild(p);
        }
    </script>

![在这里插入图片描述](https://img-blog.csdnimg.cn/20200518193134783.png

当没使用 cloneNode() 时,细心的你也许会发现,代码段运行结果跟自己想象的有点不一样,如下图:
在这里插入图片描述
你也许会有疑问,为啥只有1、3、5被追加了,而2、4还留在原地呢?其实就跟开始讲的 appendChild 移动 操作有关。

让我们来分析一下,因为有5个节点,所以会遍历5次:

1)、第一次遍历(i 的值为0)移动追加了节点1( "p text 1"),这个没问题;

2)、第二次遍历,由于节点对象 targetChildrens 是一个对象,存在引用的问题,第1次遍历完后, targetChildrens 中节点1被移走后只剩下4个元素,如下:

{
	0: <p>p text 2</p>,
	1: <p>p text 3</p>,
	2: <p>p text 4</p>,
	3: <p>p text 5</p>
}

此时 i 的值为1,所以追加了 "p text 3"

3)同理,第三次遍历, targetChildrens 中节点3被移走后只剩下3个元素,如下:

{
	0: <p>p text 2</p>,
	1: <p>p text 4</p>,
	2: <p>p text 5</p>
}

此时 i 的值为2,,所以追加了 "p text 5"

4)其实没有第四次遍历了,就是说我们初始想法中理所当然的五次遍历是 错误 的,因为经过第三次遍历之后,targetChildrens.length === 2,而此时 i 的值已为3,不再满足遍历的条件。

通过打印输出,我们可以得到验证结果:

var targetChildrens = target.children;
for (var i = 0; i < targetChildrens.length; i++) {
     console.log("i", i);
     console.log("targetChildrens", targetChildrens);
     box.appendChild(targetChildrens[i]);
}

在这里插入图片描述

当使用 cloneNode() 后,由于是克隆节点来追加,所以不会存在上面的问题:

box.appendChild( targetChildrens[i].cloneNode(true) );

在这里插入图片描述

后记,与 appendChild() 相似的方法还有 insertBefore()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值