Tüm blog yazıları

JavaScript DOM Events: Event Bubbling

JavaScript'te bir event tetiklendiğinde, sadece hedef elementte kalmayıp DOM ağacında yukarı doğru yayıldığını biliyor muydunuz? Bu kritik davranışa Event Bubbling denir. Bu yazımızda, Event Bubbling'i örneklerle açıklıyor, web uygulamalarınızdaki yaygın sorunları nasıl yöneteceğinizi gösteriyoruz.

eminbasbayan5 dk okuma
DOM ağacında yukarı doğru yayılan JavaScript olaylarını gösteren Event Bubbling görseli.

JavaScript'te event'ler tetiklendiğinde, sadece tıkladığınız veya etkileşimde bulunduğunuz elementte kalmaz. Olay, DOM ağacında yukarı doğru yayılır. Bu davranışa Event Bubbling (Olay Kabarcıklanması) denir. Bu kavramı anlamak, karmaşık web uygulamalarında beklenmedik davranışlarla karşılaşmamak için kritik öneme sahiptir.

Event Bubbling Nedir?

Bir elemente tıkladığınızda, o event önce tıklanan elementte, sonra onun parent (üst) elementinde, sonra onun da parent'ında... böyle devam ederek en üste (document ve window) kadar yayılır.

Görsel Temsil

metin
window
  └── document
        └── <html>
              └── <body>
                    └── <div class="container">
                          └── <button>Tıkla</button>  ← Tıklama burada başlar
                                    ↑
                                    ↑  Event yukarı doğru "kabarcık" gibi yükselir
                                    ↑

Basit Örnek

html
<div id="buyuk-kutu" style="padding: 50px; background: lightblue;">
    Büyük Kutu
    <div id="orta-kutu" style="padding: 30px; background: lightgreen;">
        Orta Kutu
        <button id="buton">Tıkla Beni</button>
    </div>
</div>
javascript
const buyukKutu = document.querySelector('#buyuk-kutu');
const ortaKutu = document.querySelector('#orta-kutu');
const buton = document.querySelector('#buton');

buyukKutu.addEventListener('click', function() {
    console.log('Büyük kutu tıklandı!');
});

ortaKutu.addEventListener('click', function() {
    console.log('Orta kutu tıklandı!');
});

buton.addEventListener('click', function() {
    console.log('Buton tıklandı!');
});

Butona tıkladığınızda konsol çıktısı:

metin
Buton tıklandı!
Orta kutu tıklandı!
Büyük kutu tıklandı!

Gördüğünüz gibi, sadece butona tıklasak bile, üç event handler da çalıştı! Çünkü event yukarı doğru bubble etti (kabarcıklandı).

Gerçek Hayat Problemi: Modal Kapatma

Bir modal (açılır pencere) düşünün:

html
<div id="modal-arkaplan" class="modal-arkaplan">
    <div id="modal-icerik" class="modal-icerik">
        <h2>Modal Başlık</h2>
        <p>Modal içeriği burada...</p>
        <button id="kapat-btn">Kapat</button>
    </div>
</div>
javascript
const arkaplan = document.querySelector('#modal-arkaplan');
const icerik = document.querySelector('#modal-icerik');
const kapatBtn = document.querySelector('#kapat-btn');

// Arka plana tıklanınca modal kapansın
arkaplan.addEventListener('click', function() {
    this.style.display = 'none';
    console.log('Modal kapandı - arkaplan tıklandı');
});

// Kapat butonuna tıklanınca modal kapansın
kapatBtn.addEventListener('click', function() {
    arkaplan.style.display = 'none';
    console.log('Modal kapandı - buton tıklandı');
});

Problem: Kapat butonuna tıkladığınızda iki kez "kapandı" mesajı görürsünüz! Çünkü:

  1. Önce buton click handler'ı çalışır
  2. Event bubble eder ve arkaplan click handler'ı da çalışır

Bu spesifik örnekte büyük bir sorun değil, ama bazen istenmeyen davranışlara yol açabilir.

stopPropagation(): Bubbling'i Durdurma

event.stopPropagation() metodu, event'in daha fazla yukarı yayılmasını engeller.

javascript
kapatBtn.addEventListener('click', function(event) {
    event.stopPropagation(); // Bubbling'i durdur!
    arkaplan.style.display = 'none';
    console.log('Modal kapandı - buton tıklandı');
});

Artık butona tıkladığınızda, event arkaplan'a kadar ulaşmaz.

Gerçek Hayat Örneği: Dropdown Menü

html
<div class="dropdown">
    <button class="dropdown-btn">Menü ▼</button>
    <div class="dropdown-icerik">
        <a href="#">Profil</a>
        <a href="#">Ayarlar</a>
        <a href="#">Çıkış</a>
    </div>
</div>
javascript
const dropdown = document.querySelector('.dropdown');
const dropdownBtn = document.querySelector('.dropdown-btn');
const dropdownIcerik = document.querySelector('.dropdown-icerik');

// Butona tıklanınca menüyü aç/kapat
dropdownBtn.addEventListener('click', function(event) {
    event.stopPropagation(); // Bubbling'i durdur
    dropdownIcerik.classList.toggle('goster');
});

// Menü içine tıklanınca kapanmasın
dropdownIcerik.addEventListener('click', function(event) {
    event.stopPropagation(); // Bubbling'i durdur
});

// Sayfanın herhangi bir yerine tıklanınca menüyü kapat
document.addEventListener('click', function() {
    dropdownIcerik.classList.remove('goster');
});

Bu pattern neden çalışır?

  1. Butona tıklandığında menü açılır, ama stopPropagation sayesinde document'a ulaşmaz
  2. Menü içine tıklandığında da document'a ulaşmaz
  3. Sayfanın başka bir yerine tıklandığında menü kapanır

Gerçek Hayat Örneği: Silme Butonu Olan Kart

html
<div class="kart" data-id="1">
    <h3>Ürün Adı</h3>
    <p>Ürün açıklaması...</p>
    <button class="sil-btn">Sil</button>
</div>
javascript
const kartlar = document.querySelectorAll('.kart');

kartlar.forEach(function(kart) {
    // Karta tıklanınca detay sayfasına git
    kart.addEventListener('click', function() {
        const id = this.dataset.id;
        window.location.href = `/urun/${id}`;
    });
    
    // Sil butonuna tıklanınca ürünü sil (sayfaya gitme!)
    const silBtn = kart.querySelector('.sil-btn');
    silBtn.addEventListener('click', function(event) {
        event.stopPropagation(); // Kart click'ini tetikleme!
        
        if (confirm('Silmek istediğinizden emin misiniz?')) {
            kart.remove();
        }
    });
});

Eğer stopPropagation() kullanmasaydık, sil butonuna tıkladığımızda hem silme işlemi yapılır hem de ürün detay sayfasına yönlendirilirdik!

event.target vs event.currentTarget

Bubbling'i anlamak için bu iki özelliği bilmek gerekir:

ÖzellikAçıklama
event.targetOlayı başlatan element (tıklanan)
event.currentTargetHandler'ın bağlı olduğu element
javascript
buyukKutu.addEventListener('click', function(event) {
    console.log('target:', event.target);         // Tıklanan element
    console.log('currentTarget:', event.currentTarget); // buyukKutu
});

Butona tıkladığınızda:

  • event.target → <button> (tıklanan)
  • event.currentTarget → <div id="buyuk-kutu"> (handler'ın bağlı olduğu)

Gerçek Hayat Örneği: Tablo Satır Tıklama

html
<table id="kullanici-tablosu">
    <tr data-id="1">
        <td>Ahmet</td>
        <td>ahmet@email.com</td>
        <td><button class="duzenle">Düzenle</button></td>
    </tr>
    <tr data-id="2">
        <td>Mehmet</td>
        <td>mehmet@email.com</td>
        <td><button class="duzenle">Düzenle</button></td>
    </tr>
</table>
javascript
const tablo = document.querySelector('#kullanici-tablosu');

tablo.addEventListener('click', function(event) {
    // Düzenle butonuna mı tıklandı?
    if (event.target.classList.contains('duzenle')) {
        const satir = event.target.closest('tr');
        const id = satir.dataset.id;
        console.log('Düzenleniyor:', id);
        return;
    }
    
    // Satırın herhangi bir yerine tıklandı
    const satir = event.target.closest('tr');
    if (satir) {
        const id = satir.dataset.id;
        console.log('Satır seçildi:', id);
        
        // Seçili satırı vurgula
        document.querySelectorAll('tr').forEach(s => s.classList.remove('secili'));
        satir.classList.add('secili');
    }
});

stopPropagation vs preventDefault

Bu iki metod sıkça karıştırılır:

MetodNe Yapar
stopPropagation()Event'in yukarı yayılmasını (bubbling) durdurur
preventDefault()Tarayıcının varsayılan davranışını engeller
javascript
// Örnek: Bir link içindeki buton
const link = document.querySelector('a');
const butonIcinde = link.querySelector('button');

butonIcinde.addEventListener('click', function(event) {
    event.stopPropagation();  // Link'in click handler'ını tetikleme
    event.preventDefault();   // Sayfaya gitmeyi engelle (link davranışı)
    
    console.log('Buton tıklandı, ama link çalışmadı');
});

Ne Zaman stopPropagation Kullanmalı?

✅ Kullanın:

  • Modal içindeki butonlar
  • Dropdown menüler
  • İç içe tıklanabilir elementler
  • Silme/düzenleme butonları olan kartlar

❌ Dikkatli olun:

  • Çok fazla kullanmak debugging'i zorlaştırır
  • Analytics event'lerini engelleyebilir
  • Üst düzey event listener'ları çalışmaz

Özet

Bu makalede öğrendiklerimiz:

✅ Event bubbling: Olaylar DOM ağacında yukarı doğru yayılır
✅ event.stopPropagation() ile bubbling durdurulabilir
✅ event.target tıklanan elementi, event.currentTarget handler'ın bağlı olduğu elementi gösterir
✅ Modal, dropdown ve tıklanabilir kartlarda bubbling kontrolü önemlidir
✅ stopPropagation ve preventDefault farklı amaçlara hizmet eder

Bir sonraki makalede Event Delegation (Olay Delegasyonu) konusunu inceleyeceğiz - bubbling'in güçlü bir kullanım şekli!

JavaScript Classes ile pratik uygulamalar, metotlar arası iletişim ve gerçek dünya kod örnekleri
JavaScript Dersleri9 dk okuma

JavaScript Classes - Pratik Uygulamalar

JavaScript class'ları ile pratik uygulamalara geçin! Metotlar arası iletişimden constructor'da metot çağırmaya, kod tekrarını azaltmaktan gerçek dünya senaryolarına kadar class kullanımının inceliklerini keşfedin. Kendi alışveriş sepeti örneğinizle bilginizi pekiştirin.

Yazıyı oku
JavaScript class yapısını gösteren bir kod örneği, ES6 ile modern nesne oluşturma
JavaScript Dersleri9 dk okuma

JavaScript Classes

ES6 ile JavaScript'e gelen class yapısı sayesinde nesne oluşturmak artık çok daha kolay ve düzenli! Constructor function karmaşasından kurtulup, okunabilir ve yönetilebilir kodlar yazmak isteyenler için modern JavaScript'in temel taşı olan class'ları tüm detaylarıyla keşfedin. Bu rehberle nesne şabl

Yazıyı oku
JavaScript kodunda Constructor Function ve new keyword'ü ile nesne oluşturma örnekleri
JavaScript Dersleri8 dk okuma

Constructor Functions ve new Keyword

Factory Function'ların hafıza israfı sorununa Constructor Function'lar ve new keyword'ü ile son verin! Metotları paylaştırarak JavaScript objelerini daha verimli nasıl oluşturacağınızı, new'in perde arkasında neler yaptığını ve prototype sisteminin gücünü bu rehberde keşfedin.

Yazıyı oku

Çerez tercihlerin

Platformun çalışması için zorunlu çerezler kullanıyoruz. İzin verirsen anonim kullanım verilerini ölçüyoruz. Ayrıntıları incele