jQuery / メソッド / .replaceWith() - 要素全体を置き換える
jQueryの.replaceWith(新しい内容)は選択した要素自体を置き換えます。戻り値は新要素ではなく、取り除かれた元の要素を指すjQueryオブジェクトです。以後も新要素を操作するなら別の参照を保持するか、文書から選び直します。
要素全体と内部内容の違い
.replaceWith()はDOM(Document Object Model、文書オブジェクトモデル)の元ノードと子を除き、その位置へ新内容を入れます。$(".entry").replaceWith("<section>New</section>")は外側タグ・クラス・子をsectionへ置き換えます。新sectionに.entryを指定しなければクラスは自動継承されません。
外側要素を残して内側だけ変えるなら.html()です。replaceWithにはHTML文字列、DOM要素、要素配列、jQueryオブジェクト、新内容を返す関数を渡せます。関数ではthisで各元要素を読み、必要な値を新要素へ明示的に移せます。
編集値とイベントを観察する完全な例
全コードをUTF-8のreplace-demo.htmlに保存してブラウザーで開きます。コンテンツ配信ネットワーク(CDN)の公式jQueryファイル4.0.0を読むインターネットが必要ですが、インストールは不要です。置換・入力値・イベント・初期化とConsole例を3.7.1・4.0.0で実行しました。
二つのdiv.entryをsection.entryへ変更し、名前を.text()、現在の入力値を.val()で移します。元ボタンの直接登録処理と、置換されない#boardへの委譲処理を別々に数えます。
<!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>
初期結果です。original connectedは最初の要素で文書につながる数、old dataはその要素のjQueryデータです。
live tags=div,div
original connected=2
returned original=(not run)
old data=original
direct=0; delegated=0
- 置換前にInspectを一度押すとdirect=1; delegated=1です。両方実行されます。
- Alphaの入力を編集してReplace both entriesを押します。live tagsはsection,section、original connectedは0、returned originalはtrue、old dataはundefinedです。現在値を新inputへ明示コピーするので編集値は残ります。
- 置換後のInspectはdelegatedだけ増やします。新ボタンは別ノードで直接処理を受け継ぎません。
- $returned.addClass("old-only")は除去済みノードにクラスを付けます。文書内の新sectionには付きません。開発者ツールでも戻り先を確認できます。
- 置換ボタンは一度で無効になります。Resetは元HTML・値・カウンターを戻して直接処理を再登録します。委譲処理は外側#boardへ一度だけ登録し、初期化を繰り返しても増えません。
入力値・データ・フォーカスの自動引き継ぎは仮定しません。例は現在valueをコピーしますが、フォーカスは復元しません。入力継続が必要なら新部品の参照を保持し、必要なフォーカス移動も別途設計します。
戻り値と既存ノードの移動
新要素は$newのように参照を保持してreplaceWithへ渡します。同じページの開発者ツールConsoleで次を実行してください。一時領域を作って削除するため、主例のカードは変えません。.replaceAll()は新内容から対象へ向かう書き方で、戻る集合は以下の挿入要素です。
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
文書内の既存ノードを単一対象の置換内容にすると元位置から移動します。コピーを残す動作ではありません。次は同じノードかを比較し、親なしの分離ノードでは置換の効果がないことも確認します。
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
同じid入りのHTMLを複数対象へ繰り返すとidが重複します。共通書式はクラス、必要なidは固有にします。単一対象の移動結果を複数対象の複製・移動すべてに一般化しません。各対象に新ノードが必要なら関数内で個別に生成して意図を明確にします。
処理が消える・変更が見えないとき
replaceWithは除去ノードと子のjQueryデータ・イベント処理を整理します。元の.on()処理を新ノードへコピーしません。繰り返し置換する子は、残る祖先への.on()の委譲イベントか、新ノードの初期化で対応します。この整理をネイティブaddEventListenerなど全外部状態の解放保証へ広げません。
元の選択へ.css()・.addClass()をつなぐと文書外ノードを変える場合があります。新参照か範囲を限定した再選択を使います。空の対象や親なしノードも確認し、戻り値だけで文書変更を判断しません。
HTMLを受けるメソッドに入力文字列を直接結合しません。例は固定タグを作り、名前を.text()、入力内容を.val()で渡すため<em>もタグ解釈されません。これは該当する通常テキスト・入力値の扱いであり、任意HTMLを安全に無害化する方法ではありません。




