jQuery / Método / .replaceWith() - Reemplazar elementos completos
En jQuery, .replaceWith(nuevoContenido) sustituye los propios elementos seleccionados. Devuelve el objeto jQuery de los elementos originales retirados, no de los nuevos. Para trabajar después con los nuevos elementos, guarde otra referencia o vuelva a seleccionarlos en el documento.
Elemento completo o contenido interior
.replaceWith() retira los nodos existentes y sus hijos del modelo de objetos del documento (DOM) e inserta contenido nuevo en su lugar. $(".entry").replaceWith("<section>New</section>") sustituye etiqueta exterior, clases e hijos de .entry. La nueva section no hereda .entry automáticamente.
Use .html() para conservar el elemento exterior y cambiar su contenido. replaceWith acepta una cadena HTML, un elemento DOM, un array de elementos, un objeto jQuery o una función que devuelve el contenido nuevo. En la función, this permite leer cada elemento original y transferir explícitamente los valores necesarios.
Ejemplo completo con valores editados y eventos
Guarde todo el código en UTF-8 como replace-demo.html y ábralo en el navegador. Se necesita Internet para el archivo oficial de jQuery 4.0.0 desde la red de distribución de contenido (CDN), sin instalación. La sustitución, los campos, los eventos, el reinicio y los fragmentos de consola se ejecutaron con 3.7.1 y 4.0.0.
Dos div.entry pasan a section.entry. Los nombres se trasladan con .text() y los valores actuales con .val(). Los botones originales tienen un controlador directo y otro se delega desde #board, que permanece.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Replace whole elements</title>
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<style>
body { font: 16px/1.6 sans-serif; max-width: 760px; margin: 24px auto; padding: 16px; }
button, input { font: inherit; margin: 4px; max-width: 100%; box-sizing: border-box; }
.entry { padding: 12px; border: 1px solid #aab; margin: 10px 0; }
section.entry { border: 2px solid teal; background: #edf9f6; }
pre { white-space: pre-wrap; overflow-wrap: anywhere; }
</style>
</head>
<body>
<h1>Replace the outer element</h1>
<button type="button" id="replace">Replace both entries</button>
<button type="button" id="reset">Reset</button>
<div id="board">
<div class="entry"><strong class="name">Alpha</strong><input aria-label="Alpha note" value="First note"><button type="button" class="inspect">Inspect</button></div>
<div class="entry"><strong class="name">Beta</strong><input aria-label="Beta note" value="Second note"><button type="button" class="inspect">Inspect</button></div>
</div>
<pre id="result" aria-live="polite"></pre>
<script>
$(function () {
const initial = $("#board").html();
let $old, $returned = null, direct = 0, delegated = 0;
function report() {
const tags = $("#board > .entry").map(function () { return this.tagName.toLowerCase(); }).get();
const connected = $old.filter(function () { return this.isConnected; }).length;
$("#result").text(`live tags=${tags.join(",")}\noriginal connected=${connected}\nreturned original=${$returned ? $returned === $old : "(not run)"}\nold data=${$old.first().data("lesson")}\ndirect=${direct}; delegated=${delegated}`);
}
function initialize() {
$old = $("#board > .entry").data("lesson", "original");
$old.find(".inspect").on("click.directExample", function () { direct++; });
$returned = null; direct = 0; delegated = 0;
$("#replace").prop("disabled", false);
report();
}
$("#board").on("click.replaceLesson", ".inspect", function () { delegated++; report(); });
$("#replace").on("click", function () {
$returned = $old.replaceWith(function () {
const name = $(this).find(".name").text();
const note = $(this).find("input").val();
return $("<section>", { "class": "entry" }).append(
$("<strong>", { "class": "name" }).text(name),
$("<input>", { "aria-label": name + " note" }).val(note),
$("<button>", { type: "button", "class": "inspect" }).text("Inspect")
);
});
$returned.addClass("old-only");
$(this).prop("disabled", true);
report();
});
$("#reset").on("click", function () { $("#board").html(initial); initialize(); });
initialize();
});
</script>
</body>
</html>
Esta es la salida inicial. original connected cuenta elementos originales conectados al documento; old data muestra sus datos jQuery.
live tags=div,div
original connected=2
returned original=(not run)
old data=original
direct=0; delegated=0
- Antes de sustituir, pulse una vez Inspect: direct=1; delegated=1. Se ejecutan ambos controladores.
- Edite el campo Alpha y pulse Replace both entries. live tags pasa a section,section; original connected a 0; returned original a true; old data a undefined. El valor editado se conserva por la copia explícita al input nuevo.
- Después, Inspect aumenta solo delegated. El botón nuevo es otro nodo y no hereda el controlador directo.
- $returned.addClass("old-only") añade la clase a nodos retirados. Las sections nuevas del documento no la reciben. Puede comprobarlo en las herramientas de desarrollo.
- El botón de sustitución se deshabilita tras un uso. Reset restaura HTML, valores y contadores y registra de nuevo controladores directos. La delegación se registra una vez en #board, sin duplicarse con los reinicios.
No suponga que valores, datos o foco se transfieran automáticamente. El ejemplo copia el valor actual, pero no restaura el foco. Si debe continuarse una entrada, conserve el control nuevo y diseñe aparte el movimiento de foco necesario.
Retorno y movimiento de un nodo existente
Conserve el objeto jQuery nuevo como $new antes de pasarlo a replaceWith. Ejecute este código en la consola de la misma página. Crea y elimina contenedores temporales sin modificar las tarjetas principales. .replaceAll() escribe la operación desde el contenido nuevo hacia los destinos y devuelve los elementos insertados.
const $holder = $('<div><p class="slot">A</p><p class="slot">B</p></div>').appendTo("body");
const $new = $("<section>").text("New");
const $removed = $holder.find(".slot").first().replaceWith($new);
console.log(`removed=${$removed.get(0).tagName.toLowerCase()}; new=${$new.get(0).tagName.toLowerCase()}`);
const $inserted = $("<section>").text("Another").replaceAll($holder.find(".slot"));
console.log(`replaceAll inserted=${$inserted.get(0).tagName.toLowerCase()}; live sections=${$holder.children("section").length}`);
$holder.remove();
removed=p; new=section
replaceAll inserted=section; live sections=2
Un nodo existente del documento usado para sustituir un único destino se mueve desde su ubicación anterior. No deja una copia adicional. El siguiente fragmento compara identidad y confirma que un nodo separado sin padre no cambia.
const $holder = $('<div><p class="slot">Placeholder</p><button type="button" class="source">Existing button</button></div>').appendTo("body");
const $source = $holder.find(".source");
const node = $source.get(0);
$holder.find(".slot").replaceWith($source);
console.log(`children=${$holder.children().length}; same node=${$holder.children().get(0) === node}`);
const $orphan = $("<p>Detached without parent</p>");
$orphan.replaceWith("<section>Replacement</section>");
console.log(`orphan tag=${$orphan.get(0).tagName.toLowerCase()}; connected=${$orphan.get(0).isConnected}`);
$holder.remove();
children=1; same node=true
orphan tag=p; connected=false
Repetir la misma cadena HTML con un id para varios destinos crea identificadores duplicados. Use clases para formatos compartidos e id únicos cuando hagan falta. No generalice el movimiento hacia un destino a todas las reglas de copia y movimiento con varios. Si cada destino necesita un nodo nuevo, créelo por separado dentro de una función.
Controladores perdidos y cambios invisibles
replaceWith limpia los datos y controladores jQuery de los nodos retirados y sus descendientes. No copia sus .on() a los nuevos nodos. Para hijos que se reemplazan repetidamente, use eventos delegados con .on() en un antecesor conservado o inicialice los nodos nuevos. Esta limpieza no garantiza eliminar todos los estados externos ni los listeners nativos addEventListener.
Encadenar .css() o .addClass() a la selección original puede modificar nodos fuera del documento. Use la referencia nueva o una selección nueva y limitada. Compruebe también destinos vacíos o sin padre: el retorno por sí solo no demuestra que el documento cambiara.
No concatene entradas del usuario directamente al HTML aceptado por estos métodos. El ejemplo crea etiquetas fijas y pasa nombres con .text() y campos con .val(), de modo que <em> no se interpreta como etiqueta. Eso cubre estos contextos de texto y valor, no el saneamiento de HTML arbitrario.




