Bagaimana cara menghapus hanya elemen induk dan bukan elemen anaknya di JavaScript?


89

Katakanlah:

<div>
  pre text
  <div class="remove-just-this">
    <p>child foo</p>
    <p>child bar</p>
    nested text
  </div>
  post text
</div>

untuk ini:

<div>
  pre text
  <p>child foo</p>
  <p>child bar</p>
  nested text
  post text
</div>

Saya telah mencari tahu menggunakan Mootools, jQuery dan bahkan JavaScript (mentah), tetapi tidak bisa mendapatkan ide bagaimana melakukan ini.

Jawaban:


139

Menggunakan jQuery Anda dapat melakukan ini:

var cnt = $(".remove-just-this").contents();
$(".remove-just-this").replaceWith(cnt);

Tautan cepat ke dokumentasi:

  • isi (): jQuery
  • replaceWith ( konten : [ String | Elemen | jQuery ]): jQuery

Seandainya saya menyadari (err .. menemukan ) ini 3 jam yang lalu ... sederhana dan elegan - mengagumkan!
Tathagata

3
apa pentingnya 'cnt'?
Steven Lu

1
'cnt' hanyalah nama variabel yang menyimpan "konten"
George Anderson

1
Saya tidak yakin mengapa, tetapi ini tidak berhasil untuk saya saat menggunakan konten (). Namun, ketika saya menggunakan html () di tempat konten (), itu bekerja seperti pesona!
vertigoelektrik

hanya versi 1 baris:$('.remove-just-this').replaceWith(function() { return $(this).html(); });
Taufik Nur Rahmanda

36

Metode yang tidak bergantung pustaka adalah memasukkan semua node turunan dari elemen yang akan dihapus sebelumnya (yang secara implisit menghapusnya dari posisi lamanya), sebelum Anda menghapusnya:

while (nodeToBeRemoved.firstChild)
{
    nodeToBeRemoved.parentNode.insertBefore(nodeToBeRemoved.firstChild,
                                            nodeToBeRemoved);
}

nodeToBeRemoved.parentNode.removeChild(nodeToBeRemoved);

Ini akan memindahkan semua node turunan ke tempat yang benar dalam urutan yang benar.


3
JS modern mendukung ini:node.replaceWith(...node.childNodes);
Gibolt

34

Anda harus memastikan untuk melakukan ini dengan DOM, bukan innerHTML(dan jika menggunakan solusi jQuery yang disediakan oleh jk, pastikan bahwa itu memindahkan simpul DOM daripada menggunakan secara innerHTMLinternal), untuk mempertahankan hal-hal seperti penangan kejadian.

Jawaban saya sangat mirip dengan insin, tetapi akan berkinerja lebih baik untuk struktur besar (menambahkan setiap node secara terpisah dapat membebani gambar ulang di mana CSS harus diterapkan ulang untuk masing-masing appendChild; dengan a DocumentFragment, ini hanya terjadi sekali karena tidak dibuat terlihat sampai setelahnya anak-anak semuanya ditambahkan dan itu ditambahkan ke dokumen).

var fragment = document.createDocumentFragment();
while(element.firstChild) {
    fragment.appendChild(element.firstChild);
}
element.parentNode.replaceChild(fragment, element);

Terima kasih; pendek dan langsung.
brunoais


22

Cara yang lebih elegan adalah

$('.remove-just-this').contents().unwrap();

2
Jawaban Terbaik. Terima kasih.
pengguna706420

8

Gunakan JS modern!

const node = document.getElementsByClassName('.remove-just-this')[0];
node.replaceWith(...node.childNodes); // or node.children, if you don't want textNodes

oldNode.replaceWith(newNode) adalah ES5 yang valid

...array adalah operator penyebaran, meneruskan setiap elemen array sebagai parameter


2

Pustaka mana pun yang Anda gunakan, Anda harus mengkloning div dalam sebelum menghapus div luar dari DOM. Kemudian Anda harus menambahkan div dalam hasil kloning ke tempat di DOM tempat div luar berada. Jadi langkah-langkahnya adalah:

  1. Simpan referensi ke induk div luar dalam sebuah variabel
  2. Salin div bagian dalam ke variabel lain. Ini dapat dilakukan dengan cara cepat dan kotor dengan menyimpan fileinnerHTML div bagian dalam ke variabel atau Anda dapat menyalin pohon bagian dalam secara rekursif node demi node.
  3. Panggil removeChildinduk div luar dengan div luar sebagai argumennya.
  4. Masukkan konten dalam yang disalin ke induk div luar di posisi yang benar.

Beberapa perpustakaan akan melakukan beberapa atau semua ini untuk Anda tetapi sesuatu seperti di atas akan terjadi di bawah tenda.



1

Ganti div dengan isinya:

const wrapper = document.querySelector('.remove-just-this');
wrapper.outerHTML = wrapper.innerHTML;
<div>
  pre text
  <div class="remove-just-this">
    <p>child foo</p>
    <p>child bar</p>
    nested text
  </div>
  post text
</div>


0

jika Anda ingin melakukan hal yang sama dengan piyama, begini caranya. itu bekerja dengan baik (terima kasih untuk kelopak mata). Saya bisa membuat editor teks kaya yang tepat yang melakukan gaya dengan benar tanpa mengacaukan, terima kasih untuk ini.

def remove_node(doc, element):
    """ removes a specific node, adding its children in its place
    """
    fragment = doc.createDocumentFragment()
    while element.firstChild:
        fragment.appendChild(element.firstChild)

    parent = element.parentNode
    parent.insertBefore(fragment, element)
    parent.removeChild(element)

1
Bahasa apa ini
brunoais

Sepertinya python - yang masuk akal karena pengguna menyebutkannya pyjamas.
mgilson

0

Saya mencari jawaban terbaik dari segi performa saat mengerjakan DOM penting.

Jawaban eyelidlessness menunjukkan bahwa menggunakan javascript performanya akan lebih baik.

Saya telah membuat tes waktu eksekusi berikut pada 5.000 baris dan 400.000 karakter dengan komposisi DOM yang kompleks di dalam bagian untuk dihapus. Saya menggunakan ID alih-alih kelas untuk alasan nyaman saat menggunakan javascript.

Menggunakan $ .unwrap ()

$('#remove-just-this').contents().unwrap();

201.237 md

Menggunakan $ .replaceWith ()

var cnt = $("#remove-just-this").contents();
$("#remove-just-this").replaceWith(cnt);

156.983 md

Menggunakan DocumentFragment dalam javascript

var element = document.getElementById('remove-just-this');
var fragment = document.createDocumentFragment();
while(element.firstChild) {
    fragment.appendChild(element.firstChild);
}
element.parentNode.replaceChild(fragment, element);

147,211 md

Kesimpulan

Dari segi kinerja, bahkan pada struktur DOM yang relatif besar, perbedaan antara penggunaan jQuery dan javascript tidaklah besar. Yang mengejutkan $.unwrap()lebih mahal daripada $.replaceWith(). Pengujian telah dilakukan dengan jQuery 1.12.4.


0

Jika Anda berurusan dengan beberapa baris, seperti dalam kasus penggunaan saya, Anda mungkin lebih baik menggunakan sesuatu di sepanjang baris ini:

 $(".card_row").each(function(){
        var cnt = $(this).contents();
        $(this).replaceWith(cnt);
    });
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.