jQuery / Método / .replaceWith() - Substituir elementos inteiros

No jQuery, .replaceWith(novoConteúdo) substitui os próprios elementos selecionados. O retorno é o objeto jQuery dos elementos originais removidos, não dos novos. Para trabalhar depois com os novos elementos, guarde outra referência ou selecione-os novamente no documento.

Elemento inteiro ou conteúdo interno

.replaceWith() remove os nós existentes e seus filhos do modelo de objetos do documento (DOM), inserindo novo conteúdo no lugar. $(".entry").replaceWith("<section>New</section>") substitui tag externa, classes e filhos de .entry. A nova section não herda .entry automaticamente.

Use .html() para manter o elemento externo e alterar seu conteúdo. replaceWith aceita string HTML, elemento DOM, array de elementos, objeto jQuery ou função que retorna o novo conteúdo. Na função, this permite ler cada elemento original e transferir explicitamente os valores necessários.

Exemplo completo com valores editados e eventos

Salve todo o código em UTF-8 como replace-demo.html e abra no navegador. É preciso Internet para o arquivo oficial do jQuery 4.0.0 pela rede de distribuição de conteúdo (CDN), sem instalação. Substituição, campos, eventos, restauração e trechos do Console foram executados com 3.7.1 e 4.0.0.

Dois div.entry viram section.entry. Nomes são transferidos com .text() e os valores atuais com .val(). Os botões originais recebem um manipulador direto; outro é delegado a partir de #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 é a saída inicial. original connected conta elementos originais conectados ao documento; old data mostra os dados jQuery guardados neles.

live tags=div,div
original connected=2
returned original=(not run)
old data=original
direct=0; delegated=0
  1. Antes da substituição, pressione Inspect uma vez: direct=1; delegated=1. Ambos os manipuladores executam.
  2. Edite o campo Alpha e pressione Replace both entries. live tags vira section,section; original connected vira 0; returned original fica true; old data fica undefined. O valor editado é preservado pela cópia explícita para o novo input.
  3. Depois, Inspect aumenta apenas delegated. O novo botão é outro nó e não herda o manipulador direto.
  4. $returned.addClass("old-only") adiciona a classe aos nós removidos. As novas sections do documento não a recebem. Confira também nas ferramentas do desenvolvedor.
  5. O botão de substituição fica desabilitado após um uso. Reset restaura HTML, valores e contadores e registra novamente os manipuladores diretos. A delegação é registrada uma vez em #board, sem duplicar após restaurações.

Não suponha que valores, dados ou foco sejam transferidos automaticamente. O exemplo copia o valor atual, mas não restaura o foco. Se for preciso continuar uma entrada, mantenha o novo controle e planeje separadamente o movimento de foco necessário.

Retorno e movimento de um nó existente

Guarde o novo objeto jQuery como $new antes de passá-lo a replaceWith. Execute este código no Console da mesma página. Ele cria e remove contêineres temporários sem modificar os cartões principais. .replaceAll() escreve a operação do conteúdo novo para os alvos e retorna o conjunto inserido.

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

Passar um nó já existente no documento como substituto de um único alvo o move da posição anterior. Nenhuma cópia extra fica para trás. O próximo trecho compara a identidade e confirma que um nó separado sem pai permanece inalterado.

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 a mesma string HTML com id para vários alvos cria identificadores duplicados. Use classes para formatação compartilhada e id únicos quando necessários. Não generalize o movimento de um alvo para todas as regras de cópia e movimento com vários alvos. Se cada alvo precisa de um nó novo, crie-o separadamente dentro de uma função.

Manipuladores ausentes e mudanças invisíveis

replaceWith limpa dados e manipuladores jQuery dos nós removidos e de seus descendentes. Não copia seus .on() para os novos nós. Para filhos substituídos repetidamente, use eventos delegados com .on() em um ancestral mantido ou inicialize os novos nós. Essa limpeza não garante liberar todos os estados externos ou listeners nativos addEventListener.

Encadear .css() ou .addClass() na seleção antiga pode alterar nós fora do documento. Use a referência nova ou uma nova seleção restrita. Confira também seleção vazia ou nó sem pai: o retorno sozinho não comprova mudança no documento.

Não concatene entradas do usuário diretamente ao HTML aceito por esses métodos. O exemplo cria tags fixas e passa nomes com .text() e campos com .val(), então <em> não é interpretado como tag. Isso trata esses contextos de texto e valor, não a sanitização de HTML arbitrário.