jQuery / Método / .detach() - Remover elementos e guardá-los para reutilização
No jQuery, .detach() retira os elementos selecionados do modelo de objetos do documento, DOM, preservando seus dados e eventos jQuery. Guarde o objeto jQuery devolvido ou uma referência existente em uma variável para inserir novamente. Isso não é armazenamento permanente no navegador nem no servidor.
Escolher entre detach, remove e empty
.detach() serve para retirar o mesmo elemento temporariamente e reutilizá-lo depois. O elemento e seus filhos saem juntos, mas uma referência aos nós permite reinseri-los. Diferentemente de esconder com CSS, eles não estão mais no documento e uma nova seleção nele não os encontra.
| Método | O que sai do documento | Dados/eventos jQuery das partes removidas | Uso comum |
|---|---|---|---|
| .detach() | Elementos selecionados e conteúdo | Preservados | Separação temporária e reutilização |
| .remove() | Elementos selecionados e conteúdo | Limpos | Descartar elementos |
| .empty() | Filhos e texto dos selecionados | Limpos nos filhos removidos | Esvaziar mantendo o contêiner |
.remove() não destrói necessariamente de imediato um objeto nó ainda referenciado por uma variável JavaScript. Reinseri-lo não restaura automaticamente os dados e eventos jQuery limpos. .empty() mantém o próprio contêiner. Não escolha apenas pelo mesmo efeito visual de desaparecer.
Exemplo completo preservando entrada e eventos
Salve todo o código em UTF-8 como detach-demo.html e abra no navegador. É preciso internet para carregar o arquivo oficial do jQuery 4.0.0 pela rede de distribuição de conteúdo, CDN, sem instalar pacotes. Entrada preservada, mesmo nó e posição, separação/restauração repetidas e comparações no Console foram executadas com 3.7.1 e 4.0.0.
Um nó de comentário anterior ao cartão marca sua posição. Ele permanece ao separar o cartão, permitindo que Restore o devolva ao lugar original. O cartão armazena count por .data() e seu botão filho tem um manipulador direto.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Detach and restore an editable card</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%; }
.card { border: 2px solid teal; padding: 16px; margin: 12px 0; }
</style>
</head>
<body>
<h1>Detach and restore a card</h1>
<button type="button" id="detach">Detach</button>
<button type="button" id="restore">Restore</button>
<button type="button" id="reset">Reset</button>
<div id="slot">
<p>Before the card</p>
<p id="after">After the card</p>
</div>
<p id="result" aria-live="polite"></p>
<script>
$(function () {
const anchor = document.createComment("card position");
$("#after").before(anchor);
let $saved = null;
function makeCard() {
const $card = $('<section class="card"><label>Note <input value="Keep me"></label><p>Count: <span class="count">0</span></p><button type="button" class="increment">Increment</button></section>');
$card.data("count", 0);
$card.find(".increment").on("click", function () {
const count = $card.data("count") + 1;
$card.data("count", count).find(".count").text(count);
report();
});
return $card;
}
let $card = makeCard().insertAfter(anchor);
function report() {
const attached = document.contains($card[0]);
$("#result").text(`attached=${attached} | saved=${$saved !== null} | count=${$card.data("count")}`);
}
$("#detach").on("click", function () {
if ($saved !== null) return;
$saved = $card.detach();
report();
});
$("#restore").on("click", function () {
if ($saved === null) return;
$saved.insertAfter(anchor);
$saved = null;
report();
});
$("#reset").on("click", function () {
$card.remove();
$saved = null;
$card = makeCard().insertAfter(anchor);
report();
});
report();
});
</script>
</body>
</html>
Inicialmente o cartão está no documento e não está guardado separadamente no estado destacado:
attached=true | saved=false | count=0
- Altere Note para Edited note e pressione uma vez Increment no cartão. Count passa a 1.
- Pressione Detach. O cartão some e o resultado vira
attached=false | saved=true | count=1. Os dados ficam, mas uma nova consulta de .card no documento encontra zero elementos. - Restore o devolve entre Before e After, mantendo Edited note e Count 1.
- Increment eleva Count a 2, mostrando que o manipulador do filho também foi preservado.
- Repetir Detach ou Restore não perde nem duplica o cartão porque o código verifica o estado guardado.
- Reset funciona mesmo enquanto o cartão está separado. Limpa o antigo com .remove() e cria outro com Keep me e Count 0.
Manter o valor atual do mesmo nó difere de criar um nó com outra string HTML. Restore reinsere o nó guardado; Reset cria outro de propósito. Cada cartão novo recebe o manipulador uma vez, portanto Reset repetido não multiplica os incrementos por clique.
Comparar dados e eventos com remove
Execute este trecho completo no Console das ferramentas de desenvolvimento. Ele cria dois botões em um contêiner temporário, separa um, remove o outro com remove e reinsere ambos. A última linha limpa o contêiner de teste.
const $host = $("<div>").appendTo("body");
let keptClicks = 0;
let removedClicks = 0;
const $keep = $("<button>Keep</button>").data("token", "kept")
.on("click", () => keptClicks++).appendTo($host);
const $gone = $("<button>Remove</button>").data("token", "gone")
.on("click", () => removedClicks++).appendTo($host);
const originalNode = $keep[0];
const $saved = $keep.detach();
console.log(`detached=${!document.contains($saved[0])} | data=${$saved.data("token")}`);
$saved.appendTo($host).trigger("click");
const $removed = $gone.remove();
$removed.appendTo($host).trigger("click");
console.log(`same node=${$saved[0] === originalNode} | kept clicks=${keptClicks}`);
console.log(`removed data=${typeof $removed.data("token")} | removed clicks=${removedClicks}`);
$host.remove();
detached=true | data=kept
same node=true | kept clicks=1
removed data=undefined | removed clicks=0
O botão separado é o mesmo nó e mantém token e seu manipulador: kept clicks é 1. O removido também pode ser inserido pela referência, mas seus dados jQuery são undefined e o manipulador direto foi limpo: removed clicks é 0. A comparação trata de dados e eventos gerenciados pelo jQuery; não garante limpeza de temporizadores externos ou do estado de outras bibliotecas.
Filtro por seletor e cuidados ao restaurar
O seletor de .detach(selector) filtra os membros da seleção já feita. Ele não procura novos filhos dentro deles. O exemplo de Console seleciona A e B e separa apenas B com .take, deixando A no contêiner. As duas últimas linhas limpam nós referenciados e contêiner temporário.
const $list = $('<div><p class="keep">A</p><p class="take">B</p></div>').appendTo("body");
const $items = $list.children("p");
$items.detach(".take");
console.log(`remaining=${$list.children("p").text()}`);
$items.remove();
$list.remove();
remaining=A
Uma nova consulta $(".card") após separar não recupera o cartão. Use a referência guardada e gerencie a posição anterior separadamente, por exemplo com o comentário. .appendTo() insere no final do destino e não lembra posições antigas. Um destino move o nó existente; vários podem criar cópias, então confira a quantidade.
Um evento delegado com .on() no pai depende da propagação por esse pai. Mover o elemento para outro contêiner não transporta os manipuladores delegados do pai anterior. O exemplo usa um manipulador direto no botão filho para mostrar claramente a preservação.
Se não restaurar, veja se a variável foi sobrescrita e se o marcador ou destino continua no documento. Referências mantidas por muito tempo conservam os objetos separados acessíveis. Quando a reutilização acabar, limpe o estado jQuery com .remove() e libere as referências. Cancele temporizadores e assinaturas externas pelas respectivas APIs.




