DocumentFragment: apa itu dan bagaimana (tidak) melawannya

Penafian
Sepertinya saya memulai serangkaian artikel baru - sedikit membosankan dan murni utilitarian. Mereka akan menjelaskan poin-poin yang sering menyebabkan kesulitan bagi siswa saya. Jika Anda adalah pengembang web berpengalaman, kemungkinan besar Anda tidak akan tertarik. Jika Anda menunggu penyimpangan dalam kekuatan JS Jumat, mereka tidak akan berada di sini, sayangnya.


Salah satu hal yang siswa secara teratur mengalami kesulitan memahami adalah DocumentFragment. Secara umum, saya tidak bisa menyalahkan mereka. Dengan kesederhanaan eksternal, ia memiliki beberapa sifat tidak jelas dan bahkan berlawanan dengan intuisi. Dalam artikel ini saya ingin mengumpulkan segala sesuatu yang perlu diketahui seorang pemula tentang dia.

gambar

Apa ini


DocumentFragment adalah wadah yang dapat berisi sejumlah elemen DOM yang berubah-ubah. Jika cukup sederhana, Anda bisa membayangkannya sebagai ember. Elemen-elemen ditumpuk di dalamnya sehingga pada saat yang tepat elemen-elemen tersebut dapat langsung dibuang sekaligus.

Cara membuatnya


SD.

var fragment = document.createDocumentFragment(); 

Ada juga cara lain, tetapi tentang mereka di bawah ini.

Kenapa saya perlu


Seperti yang saya tulis di atas, untuk menyimpan elemen DOM. "Tapi mereka bisa disimpan dalam diva biasa," pembaca mungkin keberatan. Benar, bagaimanapun, fragmen memiliki properti unik yang menjadikannya kandidat terbaik untuk peran ini. Pertimbangkan kode berikut:

 var fragment = document.createDocumentFragment(); var parentDiv = document.createElement("div"); var div1 = document.createElement("div"); var div2 = document.createElement("div"); fragment.appendChild(div1); fragment.appendChild(div2); //   parentDiv.appendChild(fragment); console.log(parentDiv.children); 

Apa yang akan dikatakan konsol kepada kita? Seseorang yang tidak terbiasa dengan DocumentFragment mungkin berpikir bahwa parentDiv akan memiliki satu fragment anak. Tetapi pada kenyataannya, ia akan memiliki dua anak - div1 dan div2 . Faktanya adalah fragmen itu sendiri bukan elemen DOM, itu hanya wadah untuk elemen DOM. Dan ketika dilewatkan sebagai argumen untuk metode seperti appendChild atau insertBefore , itu tidak menanamkan di pohon DOM, tetapi malah menanamkan isinya di sana.

Tetapi mengapa Anda membutuhkannya?


Properti "ember" tentu saja bagus, tetapi bagaimana hal ini berguna dalam praktik? DocumentFragment memiliki dua area utama aplikasi.

1. Menyimpan potongan-potongan HTML yang tidak memiliki leluhur yang sama.

Ada beberapa situasi ketika kita perlu mengganti konten suatu elemen, tetapi jangan menyentuh elemen itu sendiri. Misalkan kita menggunakan delegasi acara, dan semua penangan acara yang terjadi pada elemen internal digantung pada div eksternal. Dalam hal ini, DocumentFragment sangat ideal bagi kami:

 div.innerHTML = ""; div.appendChild(fragmentWithAllContent); 

"Tapi bisakah kita langsung menambahkan elemen ke div saat kita membuatnya?" - Pembaca korosif akan bertanya. Kita bisa, tetapi itu tidak sepadan, dan itulah sebabnya.

2. Peningkatan kinerja dalam hal memasukkan banyak.

Faktanya adalah bahwa setiap kali kita mengubah sesuatu di pohon DOM aktif, browser harus melakukan banyak perhitungan. Anda dapat membaca lebih lanjut tentang ini di sini , misalnya. Dalam artikel ini, kami membatasi diri untuk menyebutkan bahwa ada binatang buas yang mengerikan. Ketika kita menambahkan elemen ke halaman, binatang ini bangun dan memakan waktu prosesor. Jika kita menambahkan seratus elemen secara bergantian, binatang itu akan bangun seratus kali dan menggigitnya seratus kali. Untuk pengguna, ini mungkin sudah cukup "membeku".

Ketika kita menambahkan elemen ke DocumentFragment, ini tidak menyebabkan reflow, karena fragmen itu bukan (dan pada dasarnya tidak bisa) bagian dari pohon DOM aktif. Dan yang paling penting: ketika kita memasukkan konten sebuah fragmen menggunakan appendChild atau metode serupa lainnya, terlepas dari berapa banyak elemen di dalam fragmen, reflow disebut hanya sekali .

Untuk lebih jelasnya, saya membuat tolok ukur sederhana sehingga pembaca dapat melihat perbedaannya secara pribadi.

Upd: kawan nuit mengatakan bahwa untuk Chrome modern kata-kata saya tidak lagi benar. Di dalamnya, reflow tidak dieksekusi lebih awal dari yang diperlukan, dan berkat ini, kode tanpa DocumentFragment sebenarnya bekerja lebih cepat , dan dengan browser lain tidak begitu jelas. Jadi sebelum memutuskan apakah akan menggunakan fragmen, Anda perlu membuat profil dan meneliti audiens target situs.

Nuansa


Ada dua fitur yang membuat pemula sering sulit untuk menggunakan fragmen. Pertama: seperti yang saya tulis di atas, sebuah fragmen bukanlah elemen DOM . Ini berarti bahwa ia tidak memiliki banyak metode dan properti yang dikenal, khususnya - innerHTML . Karenanya, Anda tidak bisa hanya mengubah string menjadi konten fragmen. Cara melakukan ini tidak mudah, akan dijelaskan di bawah ini.

Fitur kedua: fragmen saat menggunakan "rampasan". Lebih tepatnya, itu dikosongkan. Ketika kita melakukan div.appendChild(fragment) , semua anak fragmen div.appendChild(fragment) dalam div . Dan karena suatu elemen tidak dapat memiliki lebih dari satu orangtua, ini berarti bahwa mereka dikeluarkan dari fragmen! Untuk menghindari perilaku ini saat tidak diinginkan, Anda dapat menggunakan cloneNode .

tag <template>


Ada satu tempat di mana Anda bisa menemukan DocumentFragment tanpa membuatnya melalui JS. Ini adalah properti content dari elemen template.

<template> diciptakan khusus untuk menyimpan potongan kode HTML, tetapi tidak untuk memuat browser sebelumnya. Apa yang ada di dalam tag ini tidak menjadi bagian dari pohon DOM aktif. Secara khusus (pendatang baru sering menemukan ini juga), mereka tidak dapat ditemukan menggunakan querySelector . Elemen yang dibuat dari kode HTML di dalam <template> tidak menjadi anak-anak darinya. Sebaliknya, JavaScript dapat mengaksesnya melalui properti content , yaitu - kejutan! - hanya DocumentFragment.

Menggunakan elemen template, Anda bisa membuat fragmen dari string:

 function createFragmentFromString(str){ var template = document.createElement("template"); template.innerHTML = str; return template.content; } 

Epilog


Jika Anda baru mengenal pengembangan web, saya harap Anda banyak belajar. Jika Anda adalah pengembang berpengalaman, Anda mungkin ingin menambah artikel ini dengan sesuatu, dalam hal ini jangan ragu untuk menuliskannya di komentar. Terima kasih sudah membaca, dan semoga harimu menyenangkan.

Source: https://habr.com/ru/post/id413287/


All Articles