Wie füge ich ein Element nach einem anderen Element in JavaScript ein, ohne eine Bibliothek zu verwenden?

757

Es gibt insertBefore()JavaScript, aber wie kann ich ein Element nach einem anderen Element einfügen, ohne jQuery oder eine andere Bibliothek zu verwenden?

Xah Lee
quelle
4
Wenn Sie den speziellen Fall des allerletzten untergeordneten
2
@ AlanLarimer das ist toll. Vielen Dank. Wissen Sie, wann insertAdjacentElement eingeführt wird?
Xah Lee
1
Laut MDN wird es in IE8 und Firefox 48 (08. August 2016) unterstützt. Folgen Sie dem Pfad: bugzilla.mozilla.org/show_bug.cgi?id=811259 -> w3.org/Bugs/Public/show_bug.cgi?id=19962 (14. März 2016)
Alan Larimer

Antworten:

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

Wo referenceNodeist der Knoten, newNodenach dem Sie setzen möchten? Wenn referenceNodees das letzte Kind in seinem übergeordneten Element ist, ist das in Ordnung, denn es referenceNode.nextSiblingwird nullund seininsertBefore Griffe , die von Fall zu Ende der Liste hinzugefügt.

Damit:

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

Sie können es mit dem folgenden Snippet testen:

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>

karim79
quelle
8
Vielen Dank für eine gute Antwort, aber ist es nicht verwirrend, referenceNode und newNode in der Argumentliste umzudrehen? Warum nicht die InsertBefore-Syntax einhalten?
GijsjanB
9
Dieses Code-Snippet wird nicht verarbeitet, wenn der referenceNode das letzte untergeordnete Element ist, in dem esChild anhängen soll.
Brad Vogel
72
Laut MDN wird der neue Knoten wie erwartet angehängt, wenn das Element das letzte ist (und somit nextSibling null ist)
elektroCutie
9
referenceNode.nextElementSibling ist eine bessere Option
Bhumi Singhal
8
@ BhumiSinghal: Falsch. insertBefore()arbeitet mit Textknoten. Warum willst du insertAfter()anders sein? Sie sollten ein separates Funktionspaar mit dem Namen insertBeforeElement()und insertAfterElement()dafür erstellen .
7vujy0f0hy
116

Einfaches JavaScript wäre das Folgende:

Vorher anhängen:

element.parentNode.insertBefore(newElement, element);

Anhängen nach:

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

Werfen Sie jedoch einige Prototypen ein, um die Verwendung zu vereinfachen

Durch Erstellen der folgenden Prototypen können Sie diese Funktion direkt aus neu erstellten Elementen aufrufen.

  • newElement.appendBefore(element);

  • newElement.appendAfter(element);

.appendBefore (Element) Prototyp

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

.appendAfter (Element) Prototyp

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

Führen Sie das folgende Code-Snippet aus, um alles in Aktion zu sehen

Führen Sie es auf JSFiddle aus

Armando
quelle
4
Die Namen der Erweiterungsfunktionen sind irreführend. Es sollte eher appendMeBefore und appendMeAfter heißen. Ich dachte, es würde wie die appendChild () -Methode verwendet , z existingElement.appendAfter(newElement);. Sehen Sie, was ich bei dieser aktualisierten jsfiddle meine .
Stomtech
2
Nach Arbeiten anhängen, denn wenn element.nextSibling kein nächstes Geschwister hat, ist nextSibling NULL und wird am Ende angehängt.
Stefan Steiger
45

insertAdjacentHTML + outerHTML

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

Vorteile:

  • DRYer: Sie müssen den Vorher-Knoten nicht in einer Variablen speichern und zweimal verwenden. Wenn Sie die Variable umbenennen, müssen Sie sie bei weniger Vorkommen ändern.
  • Golf besser als die insertBefore(Break Even, wenn der Name der vorhandenen Knotenvariablen 3 Zeichen lang ist)

Nachteile:

  • Geringere Browserunterstützung seit neuerer Version : https://caniuse.com/#feat=insert-adjacent
  • verliert Eigenschaften des Elements wie Ereignisse, da outerHTMLdas Element in eine Zeichenfolge konvertiert wird. Wir brauchen es, weil insertAdjacentHTMLInhalte eher aus Zeichenfolgen als aus Elementen hinzugefügt werden.
Ciro Santilli 冠状 病毒 审查 六四 事件 法轮功
quelle
12
Wenn Sie das Element bereits erstellt haben, können Sie.insertAdjacentElement()
GetFree
6
Ab 2018 sieht die Browserunterstützung ziemlich solide aus: caniuse.com/#feat=insert-adjacent
madannes
Dies war eine schöne Lösung, ich schlage vor, dass jeder diese xahlee.info/js/js_insert_after.html
Mehregan Rahmani
37

Eine schnelle Google-Suche zeigt dieses Skript

// 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);
    }
}
James Long
quelle
29
Für alle, die auf dieses Skript stoßen, empfehle ich nicht, es zu verwenden. Es wird versucht, Probleme zu lösen, die die native Lösung von @ karim79 bereits löst. Sein Skript ist schneller und effizienter - ich würde dringend empfehlen, dieses Skript anstelle dieses Skripts zu verwenden.
James Long
10
Als allgemeine Faustregel in JavaScript kann der Browser eine Aufgabe schneller erledigen als alles, was Sie schreiben können. Obwohl die beiden Lösungen funktional identisch sind, muss meine JavaScript-Lösung vom Browser gelesen und verstanden werden, bevor sie verwendet werden kann, und erfordert bei jeder Ausführung eine zusätzliche Überprüfung. Die von karim79 angebotene Lösung erledigt dies alles intern und speichert diese Schritte. Der Unterschied wird bestenfalls trivial sein, aber seine Lösung ist die bessere.
James Long
3
Mit anderen Worten, es wird versucht, ein Problem zu lösen, das nicht existiert. An der zusätzlichen Prüfung ist an sich nichts auszusetzen, aber ich nehme an, sie verbreitet nicht das beste Verständnis dieser Methoden
1j01
3
Ja schon. Ich lasse das Skript hier, weil ich so geschrieben habe, aber die akzeptierte Antwort ist die bessere, zeigt ein besseres Verständnis der Methoden und ist schneller. Es gibt keinen Grund, diese Antwort stattdessen zu verwenden - ich bin mir nicht einmal sicher, warum es immer noch positive Stimmen gibt
James Long
3
Wenn targetElement das letzte Element unter seinen Geschwistern ist, targetElement.nextSiblingwird es zurückgegeben null. Wenn node.insertBeforemit nullals zweitem Argument aufgerufen wird, wird der Knoten am Ende der Sammlung hinzugefügt. Mit anderen Worten, der if(parent.lastchild == targetElement) {Zweig ist überflüssig, da er parent.insertBefore(newElement, targetElement.nextSibling);alle Fälle richtig behandelt, auch wenn er auf den ersten Blick anders aussieht. Viele haben bereits in anderen Kommentaren darauf hingewiesen.
Rolf
26

Obwohl insertBefore()(siehe MDN ) großartig ist und von den meisten Antworten hier referenziert wird. Für zusätzliche Flexibilität und um etwas expliziter zu sein, können Sie Folgendes verwenden:

insertAdjacentElement()(siehe MDN ) Auf diese Weise können Sie auf ein beliebiges Element verweisen und das zu verschiebende Element genau dort einfügen, wo Sie möchten:

<!-- refElem.insertAdjacentElement('beforebegin', moveMeElem); -->
<p id="refElem">
    <!-- refElem.insertAdjacentElement('afterbegin', moveMeElem); -->
    ... content ...
    <!-- refElem.insertAdjacentElement('beforeend', moveMeElem); -->
</p>
<!-- refElem.insertAdjacentElement('afterend', moveMeElem); -->

Andere für ähnliche Anwendungsfälle zu berücksichtigen: insertAdjacentHTML()undinsertAdjacentText()

Verweise:

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

ein bisschen weniger
quelle
Sollte diese Antwort wirklich etwas Liebe geben, ist es der moderne Ansatz für die 2020er Jahre, der sich schnell nähert.
Serraosays
1
Wie kommt es, dass diese Antwort so tief vergraben ist? Ich werde einige Punkte belohnen, um mehr Aufmerksamkeit zu erregen.
Qwerty
16

Die Methode node.after( doc ) fügt einen Knoten nach einem anderen Knoten ein.

Für zwei DOM-Knoten node1und node2,

node1.after(node2)fügt node2nach node1.

Diese Methode ist in älteren Browsern nicht verfügbar, daher ist normalerweise eine Polyfüllung erforderlich.

Golopot
quelle
Die Implementierung als funktionierende Einfügung erfordert jedoch ein wenig manuelle Arbeit. Daher glaube ich leider nicht, dass dies korrekt funktionieren würde.
Mister SirCode
6

Lösung 2018 (schlechte Praxis, bis 2020)

Ich weiß, dass diese Frage uralt ist, aber für zukünftige Benutzer ist dies ein modifizierter Prototyp. Dies ist nur eine Mikro-Polyfüllung für die .insertAfter-Funktion, die nicht vorhanden ist. Dieser Prototyp fügt baseElement.insertAfter(element);dem Element-Prototyp direkt eine neue Funktion hinzu :

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

Sobald Sie die Polyfüllung in einer Bibliothek, einem Kern oder nur in Ihrem Code (oder an einer anderen Stelle, an der darauf verwiesen werden kann) platziert haben, schreiben Sie einfach document.getElementById('foo').insertAfter(document.createElement('bar'));


2019 Lösung (Hässlich, gehe zu 2020)

Neue Bearbeitung: Sie sollten keine Prototypen verwenden. Sie überschreiben die Standardcodebasis und sind nicht sehr effizient oder sicher und können Kompatibilitätsfehler verursachen. Wenn dies jedoch für nichtkommerzielle Projekte gilt, sollte dies keine Rolle spielen. Wenn Sie eine sichere Funktion für den kommerziellen Gebrauch wünschen, verwenden Sie einfach eine Standardfunktion. es ist nicht schön, aber es funktioniert:

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 Lösung

Aktuelle Webstandards für ChildNode: https://developer.mozilla.org/en-US/docs/Web/API/ChildNode

Es ist derzeit im Lebensstandard und ist sicher.

Verwenden Sie für nicht unterstützte Browser diese Polyfüllung: https://github.com/seznam/JAK/blob/master/lib/polyfills/childNode.js

Jemand erwähnte, dass die Polyfüllung Protos verwendet, als ich sagte, dass sie eine schlechte Praxis seien. Sie sind, besonders wenn sie falsch verwendet werden, wie meine Lösung für 2018. Diese Polyfüllung befindet sich jedoch in der MDN-Dokumentation und verwendet eine Art Initialisierung und Ausführung, die sicherer ist. Außerdem ist es für die Unterstützung älterer Browser gedacht, in der Zeit, in der das Überschreiben von Prototypen nicht so schlecht war.

So verwenden Sie die 2020-Lösung:

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
Herr SirCode
quelle
5

Oder Sie können einfach tun:

referenceNode.parentNode.insertBefore( newNode, referenceNode )
referenceNode.parentNode.insertBefore( referenceNode, newNode )
olvlvl
quelle
An diesen Ansatz hätte ich nicht gedacht. Ich würde es vorziehen, die direktere Antwort von @ karim79 zu verwenden , aber es ist gut, daran zu denken.
Ben J
5

Schritt 1. Elemente vorbereiten:

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

Schritt 2. Anhängen nach:

elementParent.insertBefore(newElement, element.nextSibling);
Malik Khalil
quelle
3

Die Methode insertBefore () wird wie folgt verwendet parentNode.insertBefore(). Um dies nachzuahmen und eine Methode zu parentNode.insertAfter()erstellen, können wir den folgenden Code schreiben.

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>

Beachten Sie, dass die Erweiterung des DOM möglicherweise nicht die richtige Lösung für Sie ist, wie in diesem Artikel angegeben .

Hovewer, dieser Artikel wurde 2010 geschrieben und die Dinge könnten jetzt anders sein. Entscheide dich also selbst.

JavaScript DOM insertAfter () -Methode @ jsfiddle.net

Dmytro Dzyubak
quelle
2

Idealerweise insertAftersollte ähnlich wie insertBefore funktionieren . Der folgende Code führt Folgendes aus:

  • Wenn keine Kinder vorhanden sind, wird das neue Nodeangehängt
  • Wenn keine Referenz vorhanden ist Node, wird die neue Nodeangehängt
  • Wenn Nodenach der Referenz keine vorhanden ist Node, wird die neue Nodeangehängt
  • Wenn dort die Referenz Nodeein Geschwister hat, wird das neue Nodevor diesem Geschwister eingefügt
  • Gibt das neue zurück Node

Erweitern Node

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

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

    return node;
};

Ein häufiges Beispiel

node.parentNode.insertAfter(newNode, node);

Siehe den laufenden Code

Darlesson
quelle
2

Ich weiß, dass diese Frage bereits viel zu viele Antworten hat, aber keine davon hat meine genauen Anforderungen erfüllt.

Ich wollte eine Funktion, die genau das entgegengesetzte Verhalten hatparentNode.insertBefore - das heißt, sie muss eine Null akzeptierenreferenceNode (was die akzeptierte Antwort nicht tut) und wo insertBefoream Ende der Kinder diese einfügen würde, muss diese am Anfang eingefügt werden , da sonst ' Es ist überhaupt nicht möglich, mit dieser Funktion am Startort einzufügen. der gleiche Grund insertBeforefügt am Ende ein.

Da Sie für eine Null referenceNodedas übergeordnete Element suchen müssen, müssen wir das übergeordnete Element kennen. Dies insertBeforeist eine Methode von parentNode, sodass auf diese Weise auf das übergeordnete Element zugegriffen werden kann. Unsere Funktion funktioniert nicht, daher müssen wir das übergeordnete Element als Parameter übergeben.

Die resultierende Funktion sieht folgendermaßen aus:

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

Oder (wenn Sie müssen, ich empfehle es nicht) können Sie natürlich den NodePrototyp verbessern :

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

Mit diesem Code wird ein Linkelement direkt nach dem letzten vorhandenen untergeordneten Element eingefügt, um eine kleine CSS-Datei einzufügen

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);
Chetabahana
quelle
0

Sie können verwenden appendChild Funktion verwenden, um nach einem Element einzufügen.

Referenz: http://www.w3schools.com/jsref/met_node_appendchild.asp

Doug LN
quelle
Diese Lösung funktioniert nicht für 2 p-Tags. Sie können mit dieser Funktion kein ap-Tag nach einem anderen p-Tag hinzufügen.
Mehregan Rahmani
0

eine robuste Implementierung von 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'."));

};

jszhou
quelle
Fügen Sie eine Erklärung mit Antwort hinzu, wie diese Antwort OP bei der Behebung des aktuellen Problems
hilft
Führen Sie den obigen Code aus, und fügen Sie nach dem angegebenen Referenzknoten einen neuen Knoten ein.
Jszhou
0

Behandeln wir alle Szenarien

 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);            
    }
Sami
quelle
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);
    };
}
Yavuzkavus
quelle
0

Sie können tatsächlich eine Methode verwenden, die after()in einer neueren Version von Chrome, Firefox und Opera aufgerufen wird . Der Nachteil dieser Methode ist, dass Internet Explorer sie noch nicht unterstützt.

Beispiel:

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

Ein einfacher HTML-Code zum Testen ist:

<!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>

Wie erwartet wird das Aufwärtselement nach dem Abwärtselement verschoben

Anime no Sekai
quelle