---
title: 'Şablonlar ve Yuvalar'
source: 'https://academia.sh/tr/kurslar/tarayici-platformu/sablonlar-ve-yuvalar'
course: 'Tarayıcı ve Web Platformu'
language: tr
updated: '2026-08-17T18:09:12+00:00'
license: 'CC BY-SA 4.0'
---

# Şablonlar ve Yuvalar

Çizilmeden duran işaretleme kabı ve kopyalanmasının kuralları; yuva atama algoritması, yedek içerik, düzleştirilmiş ağaç ve yerleştirilen içeriğin hangi ağaca ait kaldığı.

Önceki ders gölge ağacının nasıl yalıtıldığını gösterdi, içeriğinin nereden geldiğini
göstermedi. İki açık soru kaldı. Birincisi, bileşenin iç yapısı her örnek için düğüm düğüm
kurulursa on beş rozet on beş kez aynı kurulum kodunu çalıştırır. İkincisi, konağın belgede
yazılı ışık ağacı hiçbir yerde görünmüyor: rozetin içine yazılan başlık ve birim kayboluyor.

Bu ders iki mekanizmayı birlikte kurar: çizilmeden duran bir işaretleme kabı ve ışık
ağacındaki içeriğin gölge ağacında yerleştirileceği noktalar.

## Çizilmeyen İşaretleme Kabı

HTML'de bir öge vardır ki içeriği ayrıştırılır ama belgeye girmez: **şablon (template)**.
Ayrıştırıcı şablonun içindeki işaretlemeyi düğümlere çevirir, ancak bu düğümleri belge
ağacına değil şablona ait ayrı bir belge parçasına koyar.

Ayrımın sonucu içeriğin **edilgen** olmasıdır. Şablonun içindeki görsel indirilmez,
içindeki betik çalışmaz, içindeki biçem kuralları uygulanmaz, içindeki ögeler yerleşim
hesabına girmez. İşaretleme sayfada yazılıdır ama sayfanın hiçbir davranışına katılmaz.

Bu, bileşenin iç yapısını taşımak için doğru kaptır. İşaretleme belgede okunabilir biçimde
durur; bileşen gerektiğinde kabın içeriğini kopyalar ve kopyayı gölge ağacına koyar.
İçerik dizgiden her seferinde yeniden ayrıştırılmaz — ayrıştırma bir kez olmuştur, sonrası
ağaç kopyalamadır.

Şablonun içeriğine erişmek için ögenin çocuklarına bakmak sonuç vermez; içerik ayrı bir
parçadadır ve o parça üzerinden okunur. Bu, ilk karşılaşmada şaşırtıcı bulunan davranıştır:
şablon ögesinin çocuk düğüm sayısı sıfırdır.

## Klonlama ve Klonun Taşımadıkları

Kopyalama derin olmalıdır: yalnızca kökü değil bütün alt ağacı kopyalayan bir işlem. Sığ
kopya şablonun kökünü verir, içeriğini vermez.

Kopyanın taşımadıkları, taşıdıklarından daha öğreticidir.

**Dinleyiciler kopyalanmaz.** Şablondaki bir düğüme dinleyici bağlanmış olsa bile kopya
onu almaz; dinleyici, kopyalanan ağaç yerine yerleştirildikten sonra bağlanır. Bu bir
eksiklik değil zorunluluktur: dinleyici bir işlev başvurusudur ve işaretlemenin parçası
değildir.

**Kimlikler kopyalanır.** Şablonda bir kimlik yazılıysa her kopyada aynı kimlik oluşur.
Belge ağacında bu, kimlik benzersizliğini bozar. Gölge ağacında ise sorun doğmaz: önceki
derste görüldüğü gibi her gölge ağacının kendi kimlik uzayı vardır. Şablonlarda kimlik
kullanımının gölge ağacına bağlı olması bundandır.

**Öznitelikler kopyalanır, kullanıcı durumu kopyalanmaz.** DOM API'si dersindeki ayrım
burada da geçerlidir: kopya, özniteliklerin bildirdiği başlangıç durumunu alır; kaynak
ögede kullanıcının değiştirdiği değer kopyaya geçmez.

Kopyalama, düğümleri belgeye bağlı olmayan bir parçada üretir. DOM API'si dersinde
kurulan kural burada kendiliğinden işler: kopya hazırlanırken hiçbir yerleşim hesabı
tetiklenmez, hesap yalnızca parça gölge ağacına eklendiğinde bir kez yapılır.

## Yuvalar ve Atama Kuralı

Şablon bileşenin **kendi** yapısını verir. Bileşenin dışarıdan aldığı içerik başka bir
yerden gelir: konağın ışık ağacından. Gölge ağacı, bu içeriğin yerleştirileceği noktaları
**yuva (slot)** ögeleriyle işaretler.

Kural üç maddeye iner. Yalnızca konağın **doğrudan çocukları** atanabilir; torunlar
atanmaz. `slot` özniteliği taşıyan çocuk aynı adlı yuvaya, taşımayan çocuk adsız
varsayılan yuvaya gider. Hiçbir yuvanın adıyla eşleşmeyen çocuk hiçbir yere atanmaz ve
çizilmez.

```js
// yuva-atama.mjs — yuva atama algoritmasi ve duzlestirilmis agac
const oge = (ad, ozn = {}, ...cocuklar) => ({ ad, ozn, cocuklar, metin: null });
const metin = (deger) => ({ ad: "#metin", ozn: {}, cocuklar: [], metin: deger });
const yuva = (ad, ...yedek) => oge("slot", ad ? { name: ad } : {}, ...yedek);

function* agacta(kok) { yield kok; for (const c of kok.cocuklar) yield* agacta(c); }

const etiket = (d) =>
  d.metin !== null ? `"${d.metin}"`
  : d.ad === "slot" ? `slot[${d.ozn.name ?? "varsayilan"}]`
  : d.ad + (d.ozn.slot ? `[slot=${d.ozn.slot}]` : "");

// Atama: yalnizca konagin DOGRUDAN cocuklari atanir; slot ozniteligi olmayanlar
// varsayilan yuvaya, olanlar ayni adli yuvaya gider. Sira isik agacinin sirasidir.
function atamalar(konak, golgeKok) {
  const harita = new Map();
  for (const d of agacta(golgeKok)) if (d.ad === "slot") harita.set(d.ozn.name ?? "", []);
  for (const cocuk of konak.cocuklar) {
    const istenen = cocuk.ozn.slot ?? "";
    if (harita.has(istenen)) harita.get(istenen).push(cocuk);
  }
  return harita;
}

// Duzlestirilmis agac: her yuva, atanan dugumlerle; atama yoksa yedek icerigiyle degisir.
function duzlestir(dugum, harita, derinlik = 0, satirlar = []) {
  if (dugum.ad === "slot") {
    const atanan = harita.get(dugum.ozn.name ?? "") ?? [];
    const gorunen = atanan.length ? atanan : dugum.cocuklar;
    const kaynak = atanan.length ? "isik" : "yedek";
    for (const d of gorunen) {
      satirlar.push(`${"  ".repeat(derinlik)}${etiket(d)}   (${kaynak})`);
      for (const c of d.cocuklar) duzlestir(c, harita, derinlik + 1, satirlar);
    }
    return satirlar;
  }
  satirlar.push(`${"  ".repeat(derinlik)}${etiket(dugum)}`);
  for (const c of dugum.cocuklar) duzlestir(c, harita, derinlik + 1, satirlar);
  return satirlar;
}

// Konagin belgede yazili cocuklari (isik agaci)
const konak = oge("olcum-rozeti", { id: "sicaklik" },
  oge("span", { slot: "ad" }, metin("Sıcaklık")),
  oge("strong", {}, metin("-4.2")),
  oge("span", { slot: "birim" }, metin("°C")),
  oge("span", { slot: "kaynak" }, metin("istasyon-3")));

// Golge agaci
const golgeKok = oge("#golge-kok", {},
  oge("div", { class: "kutu" },
    yuva("ad", metin("Ölçüm")),
    oge("output", {}, yuva(null, metin("—"))),
    yuva("birim", metin("birimsiz"))));

const harita = atamalar(konak, golgeKok);
console.log("atamalar:");
for (const [ad, dugumler] of harita)
  console.log(`  slot[${ad || "varsayilan"}] ←`, dugumler.map(etiket).join(", ") || "(bos → yedek icerik)");

const atanmamis = konak.cocuklar.filter((c) => !harita.has(c.ozn.slot ?? ""));
console.log("atanmayan isik dugumleri:", atanmamis.map(etiket).join(", ") || "(yok)");

console.log("\nduzlestirilmis agac:");
console.log(duzlestir(golgeKok, harita).join("\n"));

// Isik agaci bos bir konak ayni golge agaciyla: her yuva yedek icerigini gosterir.
const bosKonak = oge("olcum-rozeti", { id: "nem" });
console.log("\nisik agaci bos konak:");
console.log(duzlestir(golgeKok, atamalar(bosKonak, golgeKok)).join("\n"));

// Isik agaci degisirse atama yeniden hesaplanir.
konak.cocuklar.push(oge("em", { slot: "birim" }, metin("°F")));
const yeni = atamalar(konak, golgeKok);
console.log("\nisik agacina em[slot=birim] eklendikten sonra:");
for (const [ad, dugumler] of yeni) {
  const oncekiler = harita.get(ad).map(etiket).join(",");
  const simdikiler = dugumler.map(etiket).join(",");
  console.log(`  slot[${ad || "varsayilan"}] ${oncekiler === simdikiler ? "degismedi" : "degisti → " + (simdikiler || "(bos)")}`);
}
```

```
atamalar:
  slot[ad] ← span[slot=ad]
  slot[varsayilan] ← strong
  slot[birim] ← span[slot=birim]
atanmayan isik dugumleri: span[slot=kaynak]

duzlestirilmis agac:
#golge-kok
  div
    span[slot=ad]   (isik)
      "Sıcaklık"
    output
      strong   (isik)
        "-4.2"
    span[slot=birim]   (isik)
      "°C"

isik agaci bos konak:
#golge-kok
  div
    "Ölçüm"   (yedek)
    output
      "—"   (yedek)
    "birimsiz"   (yedek)

isik agacina em[slot=birim] eklendikten sonra:
  slot[ad] degismedi
  slot[varsayilan] degismedi
  slot[birim] degisti → span[slot=birim],em[slot=birim]
```

Çıktının ilk bölümünde dikkat çeken satır sonuncusudur: `slot="kaynak"` yazan çocuk hiçbir
yuvayla eşleşmediği için atanmamış, dolayısıyla çizilmemiştir. Ağaçtan silinmemiştir,
belgede durmaktadır; yalnızca düzleştirilmiş ağaca girmemiştir. Bu, bileşen kullanıcısının
yaptığı yazım hatalarının sessiz kaybolmasıyla sonuçlanır ve bileşenin belgelenmiş yuva
adlarına bağımlılığını gösterir.

## Düzleştirilmiş Ağaç

Tarayıcının gerçekten çizdiği şey ne belge ağacı ne gölge ağacıdır; her yuvanın kendisine
atanan düğümlerle değiştirilmiş hâlidir. Buna **düzleştirilmiş ağaç (flattened tree)**
denir ve yerleşim ile boyama bu ağaç üzerinden yapılır.

Çıktının ikinci bölümü bunu gösterir. `slot` ögeleri düzleştirilmiş ağaçta görünmez;
yerlerinde ışık ağacından gelen düğümler durur. `strong` ögesi belge ağacında konağın
doğrudan çocuğudur, ama çizim sırasında `output` ögesinin içindedir. Düğümün ağaçtaki yeri
ile çizimdeki yeri ayrışmıştır.

Üçüncü bölüm **yedek içeriğin (fallback content)** rolünü gösterir. Bir yuvanın kendi
çocukları, o yuvaya hiçbir şey atanmadığında çizilir. Bu, bileşene varsayılan bir görünüm
kazandırır: ışık ağacı boş bir rozet birimsiz ve değersiz değil, yer tutucularıyla
görünür. Yedek içerik atama olduğu anda tümüyle devre dışı kalır; atananla karışmaz.

Son bölüm ışık ağacındaki değişikliğin atamayı yeniden hesaplattığını gösterir. Yuva
ögeleri, atamaları değiştiğinde bir olay yayar; içeriğine bağlı bir hesap yapması gereken
bileşen bu olayı dinler. Olayın çizim döngüsü içindeki yerini Zamanlama ve Çizim Döngüsü
dersindeki model verir: atama değişimi, değişikliği yapan koddan sonra bildirilir.

## Yerleştirilen İçeriğin Sahibi

Yerleştirme, düğümün ağacını değiştirmez. Yuvaya atanan `strong` ögesi belge ağacında
kalır; yalnızca çizilirken gölge ağacındaki bir noktaya taşınır. Sahiplik değişmediği için
üç davranış buradan türer.

**Biçem belgeden gelir.** Yerleştirilen düğüm belge ağacının kuralı ile biçemlenir;
gölge ağacındaki kurallar ona genel olarak eşleşmez. Bileşen, yerleştirilen düğümlere
sınırlı bir biçem verebilir: yuvaya atanmış düğümleri hedefleyen özel bir seçici vardır ve
yalnızca atanmış düğümün kendisine — çocuklarına değil — eşleşir. Bu kısıt bilinçlidir:
bileşen, kullanıcısının verdiği içeriğin iç yapısını biçemleyemez, yalnızca dış kutusunu
hizalayabilir. Çakışmada belgenin kuralı üstün gelir; bileşenin yerleştirilen içeriğe
verdiği biçem bir öneridir.

**Olaylar sınır aşımı yaşamaz.** Yerleştirilen düğümün ataları belge ağacındadır; oradaki
bir olayın hedefi çevrilmez, çünkü olay hiçbir gölge sınırı geçmemiştir. Bileşen, ışık
ağacındaki içeriğe bağlanmış dinleyicileri göremez ve görmemelidir.

**Erişilebilirlik ağacı düzleştirilmiş ağaçtan türer.** Yardımcı teknolojiye sunulan yapı,
kullanıcının gördüğü sıradır. Yuvaların gölge ağacındaki sırası okuma sırasını belirler;
ışık ağacındaki yazım sırası değil. Bileşen tasarlarken yuva sırası bir görsel tercih
değil, anlam taşıyan bir karardır.

## Özet

- Şablon ögesinin içeriği ayrıştırılır ama belgeye girmez; edilgendir, hiçbir kaynak
  yüklemez ve çizime katılmaz.
- Şablon içeriği derin kopyayla çoğaltılır; kopya öznitelikleri ve kimlikleri taşır,
  dinleyicileri ve kullanıcı durumunu taşımaz.
- Yuva atama kuralı yalnızca konağın doğrudan çocuklarına uygulanır; eşleşmeyen ad hiçbir
  yere atanmaz ve çizilmez.
- Çizilen yapı düzleştirilmiş ağaçtır: gölge ağacındaki her yuva, atanan düğümlerle ya da
  atama yoksa yedek içeriğiyle değiştirilmiş hâlidir.
- Yerleştirilen düğüm ışık ağacına ait kalır: belgenin biçemiyle biçemlenir, olayları
  gölge sınırı geçmez; bileşenin ona verebileceği biçem sınırlıdır.

## Sonraki Adım

Buraya kadar kurulan her şey sayfa yüklendikten sonra geçerlidir: öge tanımlanır, gölge
ağacı takılır, yuvalar dolar. Hepsinin öncesinde tek bir varsayım durur — bileşenin kodu,
şablonu ve verisi ağdan gelmiştir. Ağ bağlantısı zayıfladığında ya da tümüyle kesildiğinde
bu varsayım düşer ve sayfa, ne kadar iyi kapsüllenmiş olursa olsun, boş bir hata ekranına
iner. İstasyon sayfasının kullanıldığı yer buna elverişli değildir: ölçüm alan kişi
çoğunlukla kapsama alanının kıyısındadır. Sonraki ders, sayfanın isteklerini ağa
ulaşmadan önce karşılayabilen ve sayfadan bağımsız yaşayan bir katmanı kurar.
