Come inserire un elemento dopo un altro elemento in JavaScript senza usare una libreria?


757

C'è insertBefore()in JavaScript, ma come posso inserire un elemento dopo un altro elemento senza usare jQuery o un'altra libreria?


4
se avete bisogno il caso specifico della 'ultimo nodo figlio - stackoverflow.com/questions/5173545/...


2
@AlanLarimer è fantastico. Grazie. sai quando è stato inserito insertAdjacentElement?
Xah Lee,

1
Secondo MDN è supportato in IE8 e Firefox 48 (08 agosto 2016). Segui il percorso: bugzilla.mozilla.org/show_bug.cgi?id=811259 -> w3.org/Bugs/Public/show_bug.cgi?id=19962 (14 marzo 2016)
Alan Larimer,

Risposte:


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

Dov'è referenceNodeil nodo che vuoi mettere newNodedopo. Se referenceNodeè l'ultimo figlio all'interno del suo elemento genitore, va bene, perché referenceNode.nextSiblinglo sarànull e insertBeforegestirà quel caso aggiungendolo alla fine dell'elenco.

Così:

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

Puoi testarlo utilizzando il seguente frammento:

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
Grazie per un'ottima risposta, ma non è confuso capovolgere referenceNode e newNode nell'elenco degli argomenti? Perché non rispettare la sintassi insertBefore?
GijsjanB,

9
Questo frammento di codice non gestisce se referenceNode è l'ultimo figlio, in cui dovrebbe aggiungereChild.
Brad Vogel,

72
Secondo MDN se l'elemento è l'ultimo (e quindi nextSibling è null) il nuovoNode verrà aggiunto come previsto
electroCutie

9
referenceNode.nextElementSibling è un'opzione migliore da usare
Bhumi Singhal

8
@BhumiSinghal: sbagliato. insertBefore()funziona con nodi di testo. Perché vuoi insertAfter()essere diverso? È necessario creare una coppia separata di funzioni denominate insertBeforeElement()e insertAfterElement()per questo.
7vujy0f0hy

116

JavaScript semplice sarebbe il seguente:

Aggiungi prima:

element.parentNode.insertBefore(newElement, element);

Aggiungi dopo:

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

Ma, lancia alcuni prototipi lì per facilità d'uso

Creando i seguenti prototipi, sarai in grado di chiamare queste funzioni direttamente dagli elementi appena creati.

  • newElement.appendBefore(element);

  • newElement.appendAfter(element);

.appendBefore (element) Prototype

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

.appendAfter (element) Prototype

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

E, per vederlo tutto in azione, esegui il seguente frammento di codice

Eseguilo su JSFiddle


4
I nomi delle funzioni di estensione sono fuorvianti. Pensa che dovrebbe piuttosto essere chiamato appendMeBefore e appendMeAfter. Ho pensato che fosse usato come il metodo appendChild () , ad es existingElement.appendAfter(newElement);. Vedi cosa intendo in questo jsfiddle aggiornato .
stomtech,

2
Append After funziona, perché se element.nextSibling non ha un fratello successivo, nextSibling è NULL e quindi verrà aggiunto alla fine.
Stefan Steiger,

45

insertAdjacentHTML + outerHTML

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

upsides:

  • ESSICCATORE: non è necessario archiviare il nodo precedente in una variabile e utilizzarlo due volte. Se si rinomina la variabile, in caso di modifica minore.
  • golf meglio di insertBefore(interrompi anche se il nome della variabile nodo esistente è lungo 3 caratteri)

Svantaggi:

  • supporto browser inferiore dal più recente: https://caniuse.com/#feat=insert-adjacent
  • perderà proprietà dell'elemento come eventi perché outerHTMLconverte l'elemento in una stringa. Ne abbiamo bisogno perché insertAdjacentHTMLaggiunge contenuto dalle stringhe anziché dagli elementi.

12
Se avete già l'elemento costruito, è possibile utilizzare.insertAdjacentElement()
GetFree

6
A partire dal 2018, il supporto del browser sembra piuttosto solido: caniuse.com/#feat=insert-adjacent
madannes

Questa è stata una buona soluzione, suggerisco a tutti di leggere questo xahlee.info/js/js_insert_after.html
Mehregan Rahmani

37

Una rapida ricerca su Google rivela questo script

// 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
Per chiunque si imbatta in questo script, non consiglio di usarlo. Tenta di risolvere i problemi che la soluzione nativa di @ karim79 risolve già. La sua sceneggiatura è più veloce ed efficiente - consiglio vivamente di usare quella sceneggiatura invece di questa.
James Long,

10
Come regola generale in JavaScript, il browser può svolgere un'attività più velocemente di qualsiasi cosa tu possa scrivere. Sebbene le due soluzioni siano funzionalmente uguali, la mia soluzione JavaScript deve essere letta dal browser prima di poter essere utilizzata e richiede un controllo aggiuntivo ogni volta che viene eseguita. La soluzione offerta da karim79 farà tutto questo internamente, salvando questi passaggi. La differenza sarà al massimo banale, ma la sua soluzione è la migliore.
James Long,

3
In altre parole, sta tentando di risolvere un problema che non esiste. Non c'è nulla di intrinsecamente sbagliato nel controllo extra, ma suppongo che non
stia

3
Abbastanza. Lascio qui la sceneggiatura perché è il tipo di cosa che scrivevo, ma la risposta accettata è la migliore, mostra una migliore comprensione dei metodi ed è più veloce. Non c'è motivo di usare questa risposta invece - non sono nemmeno sicuro del perché ottenga ancora voti
James Long

3
Se targetElement è l'ultimo elemento tra i suoi fratelli, allora targetElement.nextSiblingtornerà null. Quando node.insertBeforeviene chiamato con nullcome secondo argomento, aggiungerà il nodo alla fine della raccolta. In altre parole, il if(parent.lastchild == targetElement) {ramo è superfluo, perché parent.insertBefore(newElement, targetElement.nextSibling);affronterà correttamente tutti i casi, anche se all'inizio potrebbe apparire diversamente. Molti lo hanno già sottolineato in altri commenti.
Rolf,

26

Anche se insertBefore()(vedi MDN ) è fantastico e indicato dalla maggior parte delle risposte qui. Per una maggiore flessibilità e per essere un po 'più esplicito, puoi usare:

insertAdjacentElement()(vedi MDN ) Ciò ti consente di fare riferimento a qualsiasi elemento e inserire l'elemento da spostare esattamente dove vuoi:

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

Altri da considerare per casi d'uso simili: insertAdjacentHTML()einsertAdjacentText()

Riferimenti:

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


Dovrebbe davvero dare un po 'di amore a questa risposta, è l'approccio moderno per gli anni 2020 che si sta rapidamente avvicinando.
serraosays,

1
Come mai questa risposta è sepolta così in profondità? Premierò alcuni punti per attirare più attenzione.
Qwerty,

16

Il metodo node.after( doc ) inserisce un nodo dopo un altro nodo.

Per due nodi DOM node1e node2,

node1.after(node2)inserti node2dopo node1.

Questo metodo non è disponibile nei browser più vecchi, quindi di solito è necessario un polyfill.


Questo richiede un po 'di lavoro manuale da implementare come un inserto funzionanteDopo però, quindi purtroppo non penso che funzionerebbe correttamente.
Mister SirCode

6

Soluzione 2018 (Bad Practice, vai al 2020)

So che questa domanda è antica, ma per tutti i futuri utenti, ecco un prototipo modificato, questo è solo un micro-riempimento per la funzione .insertAfter che non esiste questo prototipo aggiunge direttamente una nuova funzione baseElement.insertAfter(element);al prototipo Element:

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

Dopo aver inserito il polyfill in una libreria, gist o semplicemente nel tuo codice (o in qualsiasi altro luogo in cui è possibile fare riferimento) Basta scrivere document.getElementById('foo').insertAfter(document.createElement('bar'));


Soluzione 2019 (Brutto, vai al 2020)

Nuova modifica: NON DOVREI UTILIZZARE I PROTOTIPI. Sovrascrivono la base di codice predefinita e non sono molto efficienti o sicuri e possono causare errori di compatibilità, ma se è per progetti non commerciali, non dovrebbe importare. se si desidera una funzione sicura per uso commerciale, utilizzare semplicemente una funzione predefinita. non è carino ma funziona:

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 soluzione

Standard Web attuali per ChildNode: https://developer.mozilla.org/en-US/docs/Web/API/ChildNode

Attualmente è nel Living Standards ed è SICURO.

Per i browser non supportati, utilizzare questo Polyfill: https://github.com/seznam/JAK/blob/master/lib/polyfills/childNode.js

Qualcuno ha detto che il Polyfill usa Protos, quando ho detto che erano cattive pratiche. Sono, specialmente se usati in modo errato, come la mia soluzione per il 2018. Tuttavia, polyfill si trova nella documentazione MDN e utilizza una sorta di inizializzazione ed esecuzione più sicura. Inoltre, è per il supporto del browser più vecchio, nel giorno e nell'età in cui la sovrascrittura del prototipo non era così male.

Come utilizzare la soluzione 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

Oppure puoi semplicemente fare:

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

Non avrei pensato a questo approccio. Preferirei usare la risposta più diretta di @ karim79 , ma buona da tenere a mente.
Ben J,

5

Passaggio 1. Preparare gli elementi:

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

Passaggio 2. Aggiungi dopo:

elementParent.insertBefore(newElement, element.nextSibling);

3

Il metodo insertBefore () è usato come parentNode.insertBefore(). Quindi per imitare questo e creare un metodo parentNode.insertAfter()possiamo scrivere il seguente codice.

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>

Nota che l'estensione del DOM potrebbe non essere la soluzione giusta per te come indicato in questo articolo .

Hovewer, questo articolo è stato scritto nel 2010 e ora le cose potrebbero essere diverse. Quindi decidi da solo.

Metodo JavaScript insertAfter () @ jsfiddle.net


2

Idealmente insertAfterdovrebbe funzionare in modo simile a insertBefore . Il codice seguente eseguirà le seguenti operazioni:

  • Se non ci sono bambini, il nuovo Nodeviene aggiunto
  • Se non è presente alcun riferimento Node, Nodeviene aggiunto il nuovo
  • Se non c'è nessun Nodedopo il riferimento Node, il nuovo Nodeviene aggiunto
  • Se il riferimento Nodeha un fratello dopo, il nuovo Nodeviene inserito prima di quel fratello
  • Restituisce il nuovo Node

Estensione Node

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

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

    return node;
};

Un esempio comune

node.parentNode.insertAfter(newNode, node);

Vedi il codice in esecuzione


2

So che questa domanda ha già troppe risposte, ma nessuna di esse ha soddisfatto i miei esatti requisiti.

Volevo una funzione che ha il comportamento esattamente opposto diparentNode.insertBefore - cioè, deve accettare un valore nullo referenceNode(che la risposta accettata non ha) e dove insertBeforeinserire alla fine dei bambini questo deve inserire all'inizio , poiché altrimenti ci ' d non essere assolutamente possibile inserire nella posizione iniziale con questa funzione; lo stesso motivo si insertBeforeinserisce alla fine.

Poiché un null referenceNoderichiede di individuare il genitore, dobbiamo conoscere il genitore - insertBeforeè un metodo di parentNode, quindi ha accesso al genitore in quel modo; la nostra funzione no, quindi dovremo passare il genitore come parametro.

La funzione risultante è simile al seguente:

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

Oppure (se è necessario, non lo consiglio) puoi ovviamente migliorare il Nodeprototipo:

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

0

Questo codice funziona per inserire un elemento di collegamento subito dopo l'ultimo figlio esistente per incorporare un piccolo file 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

una solida implementazione di 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'."));

};


Aggiungi una spiegazione con la risposta per come questa risposta aiuta OP nel risolvere il problema attuale
ρяσѕρєя K

Eseguire il codice sopra, quindi è possibile inserire un newNode dopo il riferimento specificato.
Jszhou,

0

Gestiamo tutti gli scenari

 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

Puoi effettivamente un metodo chiamato after()nella versione più recente di Chrome, Firefox e Opera. L'aspetto negativo di questo metodo è che Internet Explorer non lo supporta ancora.

Esempio:

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

Un semplice codice HTML per testare che è:

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

Come previsto, sposta l'elemento verso l'alto dopo l'elemento verso il basso

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.