关于dom:如何在不使用库的情况下在JavaScript中的另一个元素之后插入元素?

How to insert an element after another element in JavaScript without using a library?

在JavaScript中有insertBefore(),但是如何在不使用jQuery或其他库的情况下在另一个元素之后插入元素?


1
referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);

其中referenceNode是您想要放置newNode的节点。如果referenceNode是其父元素中的最后一个子元素,那很好,因为referenceNode.nextSibling将是null并且insertBefore通过添加到列表的末尾来处理该情况。

所以:

1
2
3
function insertAfter(newNode, referenceNode) {
    referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
}

在这里试试吧。


直截了当的JavaScript将是以下:

追加之前:

1
element.parentNode.insertBefore(newElement, element);

追加后:

1
element.parentNode.insertBefore(newElement, element.nextSibling);

但是,在那里折腾一些原型以便于使用

通过构建以下原型,您将能够直接从新创建的元素中调用这些函数。

  • newElement.appendBefore(element);

  • newElement.appendAfter(element);

.appendBefore(element)原型

1
2
3
Element.prototype.appendBefore = function (element) {
  element.parentNode.insertBefore(this, element);
},false;

.appendAfter(element)原型

1
2
3
Element.prototype.appendAfter = function (element) {
  element.parentNode.insertBefore(this, element.nextSibling);
},false;

并且,要查看所有操作,请运行以下代码段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/* Adds Element BEFORE NeighborElement */
Element.prototype.appendBefore = function(element) {
  element.parentNode.insertBefore(this, element);
}, false;

/* Adds Element AFTER NeighborElement */
Element.prototype.appendAfter = function(element) {
  element.parentNode.insertBefore(this, element.nextSibling);
}, false;


/* Typical Creation and Setup A New Orphaned Element Object */
var NewElement = document.createElement('div');
NewElement.innerHTML = 'New Element';
NewElement.id = 'NewElement';


/* Add NewElement BEFORE -OR- AFTER Using the Aforementioned Prototypes */
NewElement.appendAfter(document.getElementById('Neighbor2'));
1
2
3
4
5
6
7
8
9
div {
  text-align: center;
}
#Neighborhood {
  color: brown;
}
#NewElement {
  color: green;
}
1
2
3
  Neighbor 1
  Neighbor 2
  Neighbor 3

在JSFiddle上运行它


insertAdjacentHTML + outerHTML

1
elementBefore.insertAdjacentHTML('afterEnd', elementAfter.outerHTML)

上升空间:

  • DRYer:您不必将before节点存储在变量中并使用它两次。如果重命名变量,则在较少的情况下进行修改。
  • 高尔夫球比insertBefore更好(即使现有节点变量名称为3个字符长也会中断)

缺点:

  • 更新浏览器支持:https://caniuse.com/#feat=insert-adjacent
  • 将丢失元素的属性,例如事件,因为outerHTML将元素转换为字符串。我们需要它,因为insertAdjacentHTML从字符串而不是元素添加内容。


快速Google搜索会显示此脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// create function, it expects 2 values.
function insertAfter(newElement,targetElement) {
    // target is what you want it to go after. Look for this elements parent.
    var parent = targetElement.parentNode;

    // if the parents lastchild is the targetElement...
    if (parent.lastChild == targetElement) {
        // add the newElement after the target element.
        parent.appendChild(newElement);
    } else {
        // else the target has siblings, insert the new element between the target and it's next sibling.
        parent.insertBefore(newElement, targetElement.nextSibling);
    }
}


虽然insertBefore()(参见MDN)很棒,但大多数答案都在这里引用。为了增加灵活性,并且更加明确,您可以使用:

insertAdjacentElement()(参见MDN)这允许您引用任何元素,并将要移动的元素准确插入所需的位置:

1
2
3
4
5
6
7
8
<!-- refElem.insertAdjacentElement('beforebegin', moveMeElem); -->
<p id="refElem">
    <!-- refElem.insertAdjacentElement('afterbegin', moveMeElem); -->
    ... content ...
    <!-- refElem.insertAdjacentElement('beforeend', moveMeElem); -->

</p>
<!-- refElem.insertAdjacentElement('afterend', moveMeElem); -->

其他考虑类似用例:insertAdjacentHTML()insertAdjacentText()

参考文献:

https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentElement
https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML
https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentText


node1.after(node2)产生

其中node1和node2是DOM节点。

旧浏览器[1]不支持.after(),因此您可能需要应用polyfill。


或者你可以简单地做:

1
2
referenceNode.parentNode.insertBefore( newNode, referenceNode )
referenceNode.parentNode.insertBefore( referenceNode, newNode )


Step 1. Prepare Elements :

1
2
3
var element = document.getElementById('ElementToAppendAfter');
var newElement = document.createElement('div');
var elementParent = element.parentNode;

Step 2. Append after :

1
elementParent.insertBefore(newElement, element.nextSibling);

insertBefore()方法与parentNode.insertBefore()一样使用。
因此,为了模仿这个并创建方法parentNode.insertAfter(),我们可以编写以下代码。

JavaScript的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Node.prototype.insertAfter = function(newNode, referenceNode) {
    return referenceNode.parentNode.insertBefore(
        newNode, referenceNode.nextSibling); // based on karim79's solution
};

// getting required handles
var refElem = document.getElementById("pTwo");
var parent = refElem.parentNode;

// creating <p>
paragraph three
</p>
var txt = document.createTextNode("paragraph three");
var paragraph = document.createElement("p");
paragraph.appendChild(txt);

// now we can call it the same way as insertBefore()
parent.insertAfter(paragraph, refElem);

HTML

1
2
3
4
    <p id="pOne">paragraph one
</p>
    <p id="pTwo">paragraph two
</p>

请注意,如本文所述,扩展DOM可能不适合您。

Hovewer,这篇文章写于2010年,现在情况可能有所不同。所以决定你自己。

JavaScript DOM insertAfter()方法@ jsfiddle.net


理想情况下,insertAfter应该与insertBefore类似。以下代码将执行以下操作:

  • 如果没有孩子,则附加新的Node
  • 如果没有引用Node,则追加新的Node
  • 如果在引用Node之后没有Node,则追加新的Node
  • 如果引用Node之后有一个兄弟,则在该兄弟之前插入新的Node
  • 返回新的Node

扩展Node

1
2
3
4
5
6
7
Node.prototype.insertAfter = function(node, referenceNode) {

    if (node)
        this.insertBefore(node, referenceNode && referenceNode.nextSibling);

    return node;
};

一个常见的例子

1
node.parentNode.insertAfter(newNode, node);

查看正在运行的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// First extend
Node.prototype.insertAfter = function(node, referenceNode) {
   
    if (node)
        this.insertBefore(node, referenceNode && referenceNode.nextSibling);

    return node;
};

var referenceNode,
    newNode;

newNode = document.createElement('li')
newNode.innerText = 'First new item';
newNode.style.color = '#FF0000';

document.getElementById('no-children').insertAfter(newNode);

newNode = document.createElement('li');
newNode.innerText = 'Second new item';
newNode.style.color = '#FF0000';

document.getElementById('no-reference-node').insertAfter(newNode);

referenceNode = document.getElementById('no-sibling-after');
newNode = document.createElement('li');
newNode.innerText = 'Third new item';
newNode.style.color = '#FF0000';

referenceNode.parentNode.insertAfter(newNode, referenceNode);

referenceNode = document.getElementById('sibling-after');
newNode = document.createElement('li');
newNode.innerText = 'Fourth new item';
newNode.style.color = '#FF0000';

referenceNode.parentNode.insertAfter(newNode, referenceNode);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<h5>No children</h5>
<ul id="no-children">
</ul>


<h5>No reference node</h5>
<ul id="no-reference-node">
 
<li>
First item
</li>


</ul>


<h5>No sibling after</h5>

<ul>

  <li id="no-sibling-after">First item
</li>


</ul>


<h5>Sibling after</h5>

<ul>

  <li id="sibling-after">First item
</li>

 
<li>
Third item
</li>


</ul>


我知道这个问题已经有太多的答案,但它们都没有达到我的确切要求。

我想要一个与parentNode.insertBefore具有完全相反行为的函数 - 也就是说,它必须接受一个null referenceNode(接受的答案没有),并且insertBefore将在子节点的末尾插入这个必须 在开头插入,否则根本没有办法在开始位置插入此功能; 同样的原因insertBefore在最后插入。

由于null referenceNode要求您找到父对象,我们需要知道父对象 - insertBeforeparentNode的方法,因此它可以通过这种方式访问父对象; 我们的函数没有,所以我们需要传递父作为参数。

结果函数如下所示:

1
2
3
4
5
6
function insertAfter(parentNode, newNode, referenceNode) {
  parentNode.insertBefore(
    newNode,
    referenceNode ? referenceNode.nextSibling : parentNode.firstChild
  );
}

或者(如果你必须,我不推荐它)你当然可以增强Node原型:

1
2
3
4
5
6
7
8
if (! Node.prototype.insertAfter) {
  Node.prototype.insertAfter = function(newNode, referenceNode) {
    this.insertBefore(
      newNode,
      referenceNode ? referenceNode.nextSibling : this.firstChild
    );
  };
}


您可以使用appendChild函数在元素后插入。

参考:http://www.w3schools.com/jsref/met_node_appendchild.asp


insertAfter的强大实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// source: https://github.com/jserz/domPlus/blob/master/src/insertAfter()/insertAfter.js
Node.prototype.insertAfter = Node.prototype.insertAfter || function (newNode, referenceNode) {
  function isNode(node) {
    return node instanceof Node;
  }

  if(arguments.length < 2){
    throw(new TypeError("Failed to execute 'insertAfter' on 'Node': 2 arguments required, but only"+ arguments.length +" present."));
  }

  if(isNode(newNode)){
    if(referenceNode === null || referenceNode === undefined){
      return this.insertBefore(newNode, referenceNode);
    }

    if(isNode(referenceNode)){
      return this.insertBefore(newNode, referenceNode.nextSibling);
    }

    throw(new TypeError("Failed to execute 'insertAfter' on 'Node': parameter 2 is not of type 'Node'."));
  }

  throw(new TypeError("Failed to execute 'insertAfter' on 'Node': parameter 1 is not of type 'Node'."));

};


此代码用于在最后一个现有子项之后插入链接项以内联小型css文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var raf, cb=function(){
    //create newnode
    var link=document.createElement('link');
    link.rel='stylesheet';link.type='text/css';link.href='css/style.css';

    //insert after the lastnode
    var nodes=document.getElementsByTagName('link'); //existing nodes
    var lastnode=document.getElementsByTagName('link')[nodes.length-1];
    lastnode.parentNode.insertBefore(link, lastnode.nextSibling);
};

//check before insert
try {
    raf=requestAnimationFrame||
        mozRequestAnimationFrame||
        webkitRequestAnimationFrame||
        msRequestAnimationFrame;
}
catch(err){
    raf=false;
}

if (raf)raf(cb); else window.addEventListener('load',cb);

让我们处理所有场景

1
2
3
4
5
6
7
8
9
10
11
 function insertAfter(newNode, referenceNode) {
        if(referenceNode && referenceNode.nextSibling && referenceNode.nextSibling.nodeName == '#text')
            referenceNode = referenceNode.nextSibling;

        if(!referenceNode)
            document.body.appendChild(newNode);
        else if(!referenceNode.nextSibling)
            document.body.appendChild(newNode);
        else            
            referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);            
    }

1
2
3
4
5
6
7
8
if( !Element.prototype.insertAfter ) {
    Element.prototype.insertAfter = function(item, reference) {
        if( reference.nextSibling )
            reference.parentNode.insertBefore(item, reference.nextSibling);
        else
            reference.parentNode.appendChild(item);
    };
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
 <!DOCTYPE html>
 <html lang="ca">
 <head>
    <meta charset="UTF-8">
    Document
   
        function createDiv(){
            var newDiv = document.createElement("div");
            var txt = document.createTextNode("I'm the second div");
            newDiv.appendChild(txt);
            var x = document.getElementsByTagName("BODY")[0];
            x.insertBefore(newDiv, third);
        }
   
</head>
<body>
   
        <p>

            I'm the first div
       
</p>
   
   
        <p>

            I'
m the third div
       
</p>
   
    <button type=" button" name=" button" onclick =" createDiv()">
        Create the second Div
    </button>
</body>
</html>