İçeriğe geç
JavaScript

JavaScript DOM Manipulation: Modern Yöntemler

Tarık Tunç
JavaScript DOM Manipulation: Modern Yöntemler

JavaScript DOM Manipulation: Modern Yöntemler

DOM (Document Object Model), HTML belgelerini ağaç yapısında temsil eden programlama arayüzüdür. Modern JavaScript, jQuery'ye gerek kalmadan DOM ile etkileşim kurmak için güçlü API'ler sunar. Bu rehberde eleman seçme, oluşturma, değiştirme, olay yönetimi ve performans optimizasyonu konularını ele alıyoruz.

1. Eleman Seçme

Modern JavaScript, CSS seçici sözdizimi ile DOM elemanlarına erişmek için querySelector ve querySelectorAll metotlarını sunar.

// Tek eleman seçme
const baslik = document.querySelector("h1");
const ilkKart = document.querySelector(".card");
const form = document.querySelector("#kayit-formu");
const aktifSekme = document.querySelector('[data-tab="aktif"]');

// Birden fazla eleman seçme
const tumKartlar = document.querySelectorAll(".card");
const listeler = document.querySelectorAll("ul > li:nth-child(odd)");

// NodeList üzerinde iterasyon
tumKartlar.forEach((kart, index) => {
  console.log(`Kart ${index}:`, kart.textContent);
});

// NodeList'i Array'e dönüştürme
const kartArray = [...tumKartlar];
const filtrelenmis = kartArray.filter(k => k.classList.contains("aktif"));

// Yakın eleman arama
const buton = document.querySelector(".sil-btn");
const yakinKart = buton.closest(".card");      // Üst ağaçta en yakın .card
const altBaslik = yakinKart.querySelector("h3"); // Alt ağaçta ilk h3

// matches() — CSS seçici kontrolü
if (buton.matches(".btn.btn-danger")) {
  console.log("Tehlike butonu");
}

// Geleneksel metotlar (hâlâ geçerli)
const elemanById = document.getElementById("ana-icerik");
const elemanlarByClass = document.getElementsByClassName("card"); // Canlı koleksiyon
const elemanlarByTag = document.getElementsByTagName("p");        // Canlı koleksiyon

2. Eleman Oluşturma ve Yerleştirme

Yeni DOM elemanları oluşturmak ve sayfaya eklemek için modern API'ler, eski innerHTML yaklaşımından çok daha güvenli ve esnektir.

// createElement ile eleman oluşturma
function kartOlustur({ baslik, icerik, resimUrl, etiketler }) {
  const kart = document.createElement("div");
  kart.className = "card";

  const img = document.createElement("img");
  img.src = resimUrl;
  img.alt = baslik;
  img.loading = "lazy";

  const h3 = document.createElement("h3");
  h3.textContent = baslik; // XSS güvenli (innerHTML yerine)

  const p = document.createElement("p");
  p.textContent = icerik;

  const etiketDiv = document.createElement("div");
  etiketDiv.className = "etiketler";
  etiketler.forEach(e => {
    const span = document.createElement("span");
    span.className = "etiket";
    span.textContent = e;
    etiketDiv.appendChild(span);
  });

  kart.append(img, h3, p, etiketDiv);
  return kart;
}

// DocumentFragment ile toplu ekleme (performans)
function listeOlustur(veriler) {
  const fragment = document.createDocumentFragment();

  veriler.forEach(veri => {
    const li = document.createElement("li");
    li.textContent = veri.ad;
    li.dataset.id = veri.id;
    fragment.appendChild(li);
  });

  document.querySelector("#liste").appendChild(fragment);
}

// insertAdjacentHTML — konumlu ekleme
const hedef = document.querySelector("#icerik");
hedef.insertAdjacentHTML("beforebegin", "<p>Öncesine</p>");
hedef.insertAdjacentHTML("afterbegin", "<p>İlk çocuk</p>");
hedef.insertAdjacentHTML("beforeend", "<p>Son çocuk</p>");
hedef.insertAdjacentHTML("afterend", "<p>Sonrasına</p>");

// Modern yerleştirme metotları
const referans = document.querySelector("#referans");
referans.before(yeniEleman);      // Öncesine
referans.after(yeniEleman);       // Sonrasına
referans.prepend(yeniEleman);     // İlk çocuk olarak
referans.append(yeniEleman);      // Son çocuk olarak
referans.replaceWith(yeniEleman); // Yerini al
İpucu: Çok sayıda eleman eklerken DocumentFragment kullanın. Her appendChild çağrısı DOM'u yeniden hesaplar (reflow). Fragment ile tüm elemanları tek seferde ekleyerek performansı artırabilirsiniz.

3. Olay Yönetimi (Event Handling)

Modern JavaScript'te olay yönetimi, addEventListener ile yapılır. Event delegation, custom event'ler ve AbortController ile profesyonel olay yönetimi gerçekleştirilir.

// Temel event listener
const buton = document.querySelector("#gonder-btn");
buton.addEventListener("click", (e) => {
  e.preventDefault();
  console.log("Tıklandı:", e.target);
});

// Event delegation — tek listener ile birden fazla eleman
const liste = document.querySelector("#gorev-listesi");
liste.addEventListener("click", (e) => {
  const hedef = e.target;

  if (hedef.matches(".sil-btn")) {
    hedef.closest("li").remove();
  } else if (hedef.matches(".tamamla-btn")) {
    hedef.closest("li").classList.toggle("tamamlandi");
  }
});

// AbortController ile temizleme
const controller = new AbortController();

document.addEventListener("scroll", () => {
  console.log("Kaydırılıyor...");
}, { signal: controller.signal });

document.addEventListener("resize", () => {
  console.log("Boyut değişti...");
}, { signal: controller.signal });

// Tek çağrı ile tüm listener'ları kaldır
function temizle() {
  controller.abort();
}

// Custom event
const sepetEvent = new CustomEvent("urunEklendi", {
  detail: { urunId: 42, ad: "Laptop", fiyat: 25000 },
  bubbles: true
});

document.querySelector("#sepet").dispatchEvent(sepetEvent);

document.addEventListener("urunEklendi", (e) => {
  console.log("Sepete eklendi:", e.detail);
});

4. Stil ve Sınıf Yönetimi

const eleman = document.querySelector(".kutu");

// classList API
eleman.classList.add("aktif", "animasyonlu");
eleman.classList.remove("gizli");
eleman.classList.toggle("acik");
eleman.classList.replace("eski-tema", "yeni-tema");
console.log(eleman.classList.contains("aktif")); // true

// Inline stil
eleman.style.backgroundColor = "#f0f0f0";
eleman.style.setProperty("--ana-renk", "#3498db");

// Computed style okuma
const stil = getComputedStyle(eleman);
console.log(stil.fontSize);    // "16px"
console.log(stil.getPropertyValue("--ana-renk"));

// data-* attribute'ları
eleman.dataset.kullaniciId = "42";
eleman.dataset.aktifSayfa = "3";
console.log(eleman.dataset.kullaniciId); // "42"
// HTML: <div data-kullanici-id="42" data-aktif-sayfa="3">

// Toplu stil değişikliği (CSS class ile)
function temaUygula(temaAdi) {
  document.documentElement.setAttribute("data-tema", temaAdi);
}
Uyarı: innerHTML kullanıcı girdisi ile kullanıldığında XSS (Cross-Site Scripting) açığına neden olur. Kullanıcı girdisi içeren içerikler için her zaman textContent veya DOM API metotları kullanın.
Bilgi: querySelectorAll statik bir NodeList döner (anlık görüntü), getElementsByClassName ise canlı bir HTMLCollection döner (DOM değişikliklerini otomatik yansıtır). Performans açısından kritik durumlarda bu farkı göz önünde bulundurun.

Sonuç

Modern JavaScript DOM API'leri, jQuery benzeri kütüphanelere ihtiyaç duymadan güçlü ve verimli DOM manipülasyonu yapmayı mümkün kılar. querySelector/querySelectorAll ile eleman seçme, DocumentFragment ile performanslı ekleme, event delegation ile verimli olay yönetimi ve classList API ile kolay stil kontrolü, modern web geliştirmenin temel araçlarıdır.

Kaynaklar

İlgili Yazılar