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


757

还有insertBefore()在JavaScript,但我怎么能插入一个元素后,另一种元素,而不使用jQuery或其他库?


4
如果你需要的最后一个子节点的具体情况- stackoverflow.com/questions/5173545/...


2
@AlanLarimer太好了。谢谢。您知道何时引入insertAdjacentElement吗?
Xah Lee

1
根据MDN的说明,IE8和Firefox 48(2016年8月8日)支持该功能。遵循足迹:bugzilla.mozilla.org/show_bug.cgi? id=811259- > w3.org/Bugs/Public/show_bug.cgi?id=19962(2016年 3月14日)
艾伦·拉里默

Answers:


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

referenceNode您要放置的节点在哪里newNode。If referenceNode是其父元素中的最后一个子元素,这很好,因为referenceNode.nextSibling它将是,nullinsertBefore通过添加到列表的末尾来处理这种情况。

所以:

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

您可以使用以下代码段对其进行测试:

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

var el = document.createElement("span");
el.innerHTML = "test";
var div = document.getElementById("foo");
insertAfter(div, el);
<div id="foo">Hello</div>


8
感谢您提供一个很好的答案,但是在参数列表中翻转referenceNode和newNode会不会引起混淆?为什么不遵守insertBefore语法?
GijsjanB 2013年

9
如果referenceNode是应该在其中添加appendChild的最后一个子代,则此代码段将无法处理。
布拉德·沃格尔

72
根据MDN,如果元素为最后一个元素(因此nextSibling为null),则将按预期方式附加newNode
electroCutie 2014年

9
referenceNode.nextElementSibling是一个更好的选择
Bhumi Singhal

8
@BhumiSinghal:错了。insertBefore()适用于文本节点。为什么要insertAfter()与众不同?您应该创建一个单独的对命名的功能insertBeforeElement()insertAfterElement()为。
7vujy0f0hy

116

简单的JavaScript将是以下内容:

附加之前:

element.parentNode.insertBefore(newElement, element);

追加时间:

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

但是,为了方便使用,扔了一些原型

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

  • newElement.appendBefore(element);

  • newElement.appendAfter(element);

.appendBefore(element)原型

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

.appendAfter(element)原型

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

并且,要查看全部内容,请运行以下代码段

在JSFiddle上运行


4
扩展功能名称误导。它认为应该将其称为appendMeBefore和appendMeAfter。我认为它的用法类似于appendChild()方法,例如existingElement.appendAfter(newElement);。看看我在这个更新的jsfiddle中的意思
stomtech

2
Append After工作正常,因为如果element.nextSibling没有下一个同级,则nextSibling为NULL,然后它将在末尾附加。
Stefan Steiger,

45

insertAdjacentHTML + outerHTML

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

优点:

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

缺点:

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

12
如果您已经构造了元素,则可以使用.insertAdjacentElement()
GetFree

6
截至2018年,浏览器支持看起来非常稳定:caniuse.com/#feat=insert-adjacent
madannes,

这是一个不错的解决方案,我建议eveyone阅读xahlee.info/js/js_insert_after.html
Mehregan Rahmani,

37

快速的Google搜索显示了此脚本

// 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);
    }
}

29
对于偶然发现此脚本的任何人,我建议您不要使用它。它试图解决@ karim79的本机解决方案已经解决的问题。他的脚本更快,更高效-我强烈建议您使用该脚本而不是此脚本。
James Long

10
作为JavaScript的通用规则,浏览器可以比编写任何东西更快地完成任务。尽管这两个解决方案在功能上是相同的,但是我的JavaScript解决方案必须先被浏览器理解才能使用,并且每次执行时都需要进行额外的检查。karim79提供的解决方案将在内部完成所有这些工作,从而节省了这些步骤。这种差异充其量是微不足道的,但他的解决方案是更好的解决方案。
James Long

3
换句话说,它正在尝试解决不存在的问题。额外的检查没有任何内在的错误,但是我想它并没有传播对这些方法的最佳理解
1j01

3
差不多了 我将脚本留在这里是因为这是我以前写的那种东西,但是公认的答案是更好的答案,对方法有更好的理解,而且速度更快。没有理由使用这个答案,而不是-我甚至不知道为什么它仍然得到upvotes
詹姆斯龙

3
如果targetElement是同级元素中的最后一个元素,targetElement.nextSibling则将返回null。当node.insertBeforenull作为第二个参数调用时,它将在集合的末尾添加节点。换句话说,该if(parent.lastchild == targetElement) {分支是多余的,因为parent.insertBefore(newElement, targetElement.nextSibling);即使最初可能会出现其他情况,它也可以正确处理所有情况。许多人已经在其他评论中指出了这一点。
罗尔夫

26

尽管insertBefore()(请参见MDN)很棒,但这里的大多数答案都引用了它。为了增加灵活性并更加明确,可以使用:

insertAdjacentElement()(请参阅MDN)这使您可以引用任何元素,并将要移动的元素准确插入所需的位置:

<!-- 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/zh-CN/docs/Web/API/Element/insertAdjacentElement https://developer.mozilla.org/zh-CN/docs/Web/API/Element/insertAdjacentHTML https:// developer.mozilla.org/zh-CN/docs/Web/API/Element/insertAdjacentText


真的应该给这个答案一些爱,这是2020年代即将到来的现代方法。
serraosays

1
这个答案怎么这么深?我会在某些方面给予奖励,以引起更多关注。
Qwerty

16

方法node.afterdoc)在另一个节点之后插入一个节点。

对于两个DOM节点node1node2

node1.after(node2)node2在之后插入node1

此方法在较旧的浏览器中不可用,因此通常需要一个polyfill。


但是,要实现功能正常的insertAfter,这需要一些手动工作,因此很遗憾,我认为这不能正常工作。
SirCode先生,

6

2018解决方案(Bad Practice,转到2020)

我知道这个问题很古老,但是对于任何将来的用户来说,这是一个经过修改的原型,这只是.insertAfter函数的微型填充,该函数不存在,该原型直接baseElement.insertAfter(element);向Element原型添加了一个新功能:

Element.prototype.insertAfter = function(new) {
    this.parentNode.insertBefore(new, this.nextSibling);
}

将polyfill放在库,要旨中或仅在代码中(或其他可以引用它的地方)后,只需编写 document.getElementById('foo').insertAfter(document.createElement('bar'));


2019解决方案(丑陋,请到2020)

新建编辑:您不应该使用原型。它们会覆盖默认代码库,并且效率很高或非常安全,并且会导致兼容性错误,但如果是非商业项目,则不重要。 如果您想将安全功能用于商业用途,请使用默认功能。它不漂亮,但可以工作:

function insertAfter(el, newEl) {
    el.parentNode.insertBefore(newEl, this.nextSibling);
}

// use

const el = document.body || document.querySelector("body");
// the || means "this OR that"

el.insertBefore(document.createElement("div"), el.nextSibling);
// Insert Before

insertAfter(el, document.createElement("div"));
// Insert After 


2020解决方案

当前适用于ChildNode的Web标准:https : //developer.mozilla.org/en-US/docs/Web/API/ChildNode

目前在生活标准中,并且是SAFE。

对于不受支持的浏览器,请使用以下Polyfill:https : //github.com/seznam/JAK/blob/master/lib/polyfills/childNode.js

有人提到,Polyfill使用Protos,这是我的不当做法。它们是特别是在不正确使用它们的情况下,例如我在2018年提出的解决方案。但是,该polyfill在MDN文档中,并且使用了一种更安全的初始化和执行。加上它是用于较早的浏览器支持的,在如今原型覆盖还算不错的时代。

如何使用2020解决方案:

const el = document.querySelector(".class");

// Create New Element
const newEl = document.createElement("div");
newEl.id = "foo";

// Insert New Element BEFORE
el.before(newEl);

// Insert New Element AFTER
el.after(newEl);

// Remove Element
el.remove();

// Remove Child
newEl.remove(); // This one wasnt tested but should work

5

或者您可以简单地执行以下操作:

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

我不会想到这种方法。我希望使用@ karim79的更直接的答案,但请记住。
本J

5

步骤1.准备元素:

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

步骤2.在之后附加:

elementParent.insertBefore(newElement, element.nextSibling);

3

insertBefore()方法的用法类似于parentNode.insertBefore()。因此,为了模仿这一点并提出一种方法,parentNode.insertAfter()我们可以编写以下代码。

的JavaScript

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

<div id="divOne">
    <p id="pOne">paragraph one</p>
    <p id="pTwo">paragraph two</p>
</div>

请注意,这延长了DOM可能不适合你的解决方案中所述这篇文章

Hovewer,这篇文章写于2010年,现在情况可能有所不同。因此,请自行决定。

JavaScript DOM insertAfter()方法@ jsfiddle.net


2

理想情况下insertAfter,其工作方式应类似于insertBefore。下面的代码将执行以下操作:

  • 如果没有子代,Node则附加新的子代
  • 如果没有参考NodeNode则附加新的
  • 如果Node在引用之后没有NodeNode则附加新的
  • 如果引用Node后面有一个同级,则Node在该同级之前插入新的同级
  • 返回新的 Node

延伸 Node

Node.prototype.insertAfter = function(node, referenceNode) {

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

    return node;
};

一个常见的例子

node.parentNode.insertAfter(newNode, node);

查看正在运行的代码


2

我知道这个问题已经有太多答案了,但是没有一个答案符合我的确切要求。

我想要一个与以下行为完全相反的函数parentNode.insertBefore -也就是说,它必须接受null referenceNode接受的答案接受),并且insertBefore必须在子项的末尾插入,该子项必须在开始处插入,否则会出现这种情况。 d根本无法使用此功能插入起始位置;insertBefore在末尾插入相同的原因。

由于null referenceNode需要您定位父对象,因此我们需要知道父对象- insertBefore是的方法parentNode,因此它可以通过这种方式访问​​父对象;我们的函数没有,所以我们需要将parent作为参数传递。

结果函数如下所示:

function insertAfter(parentNode, newNode, referenceNode) {
  parentNode.insertBefore(
    newNode,
    referenceNode ? referenceNode.nextSibling : parentNode.firstChild
  );
}

或者(如果您必须,我不推荐这样做)您当然可以增强Node原型:

if (! Node.prototype.insertAfter) {
  Node.prototype.insertAfter = function(newNode, referenceNode) {
    this.insertBefore(
      newNode,
      referenceNode ? referenceNode.nextSibling : this.firstChild
    );
  };
}

0

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

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);


0

insertAfter的可靠实现。

// 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'."));

};


与答案添加一些解释如何回答帮助OP在固定电流问题
ρяσѕρєяķ

运行上面的代码,然后您可以在指定的referenceNode之后插入一个newNode。
jszhou

0

让我们处理所有情况

 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);            
    }

0
if( !Element.prototype.insertAfter ) {
    Element.prototype.insertAfter = function(item, reference) {
        if( reference.nextSibling )
            reference.parentNode.insertBefore(item, reference.nextSibling);
        else
            reference.parentNode.appendChild(item);
    };
}

0

实际上,您可以after()在较新版本的Chrome,Firefox和Opera中调用一种方法。这种方法的缺点是Internet Explorer尚不支持它。

例:

// You could create a simple node
var node = document.createElement('p')

// And then get the node where you want to append the created node after
var existingNode = document.getElementById('id_of_the_element')

// Finally you can append the created node to the exisitingNode
existingNode.after(node)

要测试的简单HTML代码是:

<!DOCTYPE html>
<html>
<body>
     <p id='up'>Up</p>
    <p id="down">Down</p>
  <button id="switchBtn" onclick="switch_place()">Switch place</button>
  <script>
    function switch_place(){
      var downElement = document.getElementById("down")
      var upElement = document.getElementById("up")
      downElement.after(upElement);
      document.getElementById('switchBtn').innerHTML = "Switched!"
    }
  </script>
</body>
</html>

不出所料,它将up元素移到down元素之后

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.