7 Teknik Manipulasi DOM JavaScript yang Sering Terlupa

Tujuh teknik manipulasi DOM JavaScript yang sering terlewat: dari DocumentFragment hingga event delegation, bikin kode lebih efisien dan mudah dirawat.

Tangan pengembang mengetik kode JavaScript untuk manipulasi DOM di laptop

Saat menambahkan sepuluh item ke daftar belanja, kode kita mungkin berjalan mulus. Begitu jumlahnya ratusan, halaman mulai tersendat. Penyebabnya sering bukan logika bisnis, melainkan cara kita menyentuh DOM. Ada banyak teknik manipulasi DOM JavaScript yang jarang dibahas di tutorial dasar, padahal bisa menghemat waktu dan mengurangi beban render.

Tujuh teknik berikut layak masuk kotak alat koding harian. Setiap poin disertai contoh singkat dan alasan teknik itu berguna.

1. Bungkus banyak elemen dengan DocumentFragment

Setiap kali kita memanggil appendChild ke elemen yang sudah menempel di halaman, browser bisa memicu perhitungan layout. Jika dilakukan dalam loop, biayanya menumpuk. DocumentFragment adalah wadah ringan di luar dokumen. Kita menambahkan semua elemen baru ke fragment, lalu menempelkan fragment sekali saja ke DOM.

const list = document.querySelector('#daftar');
const fragment = document.createDocumentFragment();
for (let i = 0; i < 100; i++) {
  const li = document.createElement('li');
  li.textContent = `Item ${i + 1}`;
  fragment.appendChild(li);
}
list.appendChild(fragment);

Hasilnya, browser hanya memproses satu operasi penyisipan. Teknik ini sering dipakai saat membangun daftar dari data array, terutama jika datanya berasal dari API.

2. Kloning node untuk template yang berulang

Membuat elemen dari nol dengan createElement berulang kali melelahkan, apalagi kalau struktur HTML-nya cukup dalam. Jika kita punya template tersembunyi di HTML, kita bisa mengkloningnya dengan cloneNode(true).

<template id="kartu-template">
  <div class="kartu">
    <h3 class="judul"></h3>
    <p class="deskripsi"></p>
  </div>
</template>
const template = document.getElementById('kartu-template');
const wadah = document.querySelector('.wadah');
const salinan = template.content.cloneNode(true);
salinan.querySelector('.judul').textContent = 'Judul Baru';
wadah.appendChild(salinan);

Elemen <template> tidak dirender sampai kita menggunakannya, jadi aman disimpan di akhir body. Pendekatan ini membuat markup tetap di HTML dan logika tetap di JavaScript.

3. Event delegation: satu listener untuk banyak elemen

Menambahkan event listener ke setiap tombol dalam daftar panjang boros memori. Event delegation memanfaatkan bubbling: kita pasang listener di parent, lalu periksa target sebenarnya dengan event.target.closest().

document.querySelector('#daftar-tombol').addEventListener('click', (e) => {
  const tombol = e.target.closest('.hapus');
  if (!tombol) return;
  tombol.closest('li').remove();
});

Selain hemat listener, teknik ini tetap bekerja untuk elemen yang ditambahkan setelah listener terpasang. Cocok untuk daftar dinamis, menu dropdown, atau tabel yang barisnya sering berubah.

4. Gunakan classList untuk mengubah gaya

Mengatur element.style.backgroundColor satu per satu membuat kode sulit dirawat dan mencampur presentasi ke dalam JavaScript. classList memungkinkan kita menambah, menghapus, atau mengganti kelas dengan rapi.

const kartu = document.querySelector('.kartu');
kartu.classList.add('aktif');
kartu.classList.remove('nonaktif');
kartu.classList.toggle('sorot');

Dengan cara ini, semua aturan visual tetap di CSS. Jika desain berubah, kita hanya menyunting stylesheet, bukan puluhan baris JavaScript.

5. Batasi pembacaan layout dengan requestAnimationFrame

Membaca properti seperti offsetWidth atau getBoundingClientRect() memaksa browser menghitung layout. Jika dilakukan berulang dalam loop, muncul layout thrashing. Bungkus pembacaan dan penulisan dalam requestAnimationFrame agar sinkron dengan siklus render.

function animasi() {
  const kotak = document.querySelector('.kotak');
  const lebar = kotak.offsetWidth;
  kotak.style.transform = `translateX(${lebar}px)`;
  requestAnimationFrame(animasi);
}
requestAnimationFrame(animasi);

Untuk animasi yang lebih kompleks, pertimbangkan CSS transition atau Web Animations API. Artikel Memilih Antara setTimeout, setInterval, dan requestAnimationFrame membahas kapan masing-masing cocok dipakai.

6. Simpan referensi elemen, jangan query berulang

document.querySelector memang cepat, tapi memanggilnya di dalam loop atau event handler yang sering terpicu tetap membuang waktu. Simpan hasilnya dalam variabel di luar fungsi.

const tombol = document.querySelector('#simpan');
const input = document.querySelector('#nama');

tombol.addEventListener('click', () => {
  console.log(input.value);
});

Kebiasaan ini juga membantu saat debugging: kita tahu persis elemen mana yang sedang dipegang. Jika struktur DOM berubah, cukup perbarui satu baris.

7. Hapus elemen dengan remove() dan ganti konten dengan replaceChildren

Dulu kita menghapus elemen dengan parentNode.removeChild(child). Sekarang ada element.remove() yang lebih ringkas. Untuk mengganti seluruh isi kontainer, replaceChildren() menghapus semua anak lalu menambahkan yang baru dalam satu panggilan.

const kontainer = document.querySelector('#hasil');
kontainer.replaceChildren(); // kosongkan
// atau ganti dengan elemen baru
const baru = document.createElement('p');
baru.textContent = 'Data diperbarui';
kontainer.replaceChildren(baru);

Metode ini didukung di browser modern. Kalau harus mendukung browser lama, sediakan fallback dengan innerHTML = '' atau loop removeChild.

Merangkum

Tujuh teknik di atas menutup celah yang sering terlewat saat menulis kode DOM: mengurangi reflow, menghindari listener berlebih, dan menjaga logika tetap terpisah dari gaya. Mulailah dari satu teknik yang paling relevan dengan proyek saat ini, lalu terapkan secara konsisten. Untuk manipulasi data sebelum ditampilkan, lihat juga 7 Metode Array JavaScript untuk Mengolah Data Sehari-hari.

Pertanyaan yang Sering Diajukan

Apakah DocumentFragment bisa dipakai untuk mengganti konten yang sudah ada?

Bisa. Setelah fragment diisi, panggil replaceChildren(fragment) pada kontainer. Fragment akan dipindahkan isinya ke DOM dan wadahnya menjadi kosong. Ini lebih efisien daripada menghapus anak satu per satu lalu menambahkan yang baru.

Kapan sebaiknya memakai event delegation?

Saat jumlah elemen anak banyak atau dinamis, misalnya daftar yang bisa bertambah dan berkurang. Untuk satu tombol statis, listener langsung lebih sederhana. Event delegation juga berguna jika kita ingin menangani klik pada elemen yang belum ada saat halaman dimuat.

Apakah querySelector cukup cepat untuk aplikasi besar?

Untuk sebagian besar kasus, ya. Namun jika dipanggil ribuan kali per detik, simpan referensinya. Alternatif lain adalah getElementById yang sedikit lebih cepat untuk id, atau menyimpan cache elemen di objek modul agar tidak query ulang.