Ders 02 / 22
İç İçe Rotalar ve Düzenler
Rotaların ağaç biçiminde tanımlanması; düzen bileşenleri ve alt görünüm yuvası, dizin rotası, eşleşmeden üretilen etkin düzen zinciri, gezinmede korunan kabuk ve parametre değişiminin ayrı ele alınması.
İçindekiler
Önceki dersin eşleyicisi düz bir tablo üzerinde çalıştı: her yol tek bir görünüme bağlandı. Kuzey Yamaç Ölçüm İstasyonu uygulamasının ekranları ise ortak bir kabuk paylaşıyor. İstasyon ayrıntısı ile ölçüm geçmişi aynı üst başlığı, aynı yan gezinmeyi ve aynı istasyon künyesini gösteriyor; yalnızca ortadaki bölge değişiyor.
Düz tabloyla bu ortak kabuk her rotanın bileşeninde yeniden kurulmak zorundadır. Sonucu üç ayrı kusurdur: aynı işaretleme birden çok yerde yinelenir, gezinmede kabuk yeniden çizilir, kabuğun içindeki durum — açık bir menü, kaydırılmış bir liste — her gezinmede sıfırlanır. Bu ders rotaları ağaç biçiminde tanımlayarak üçünü birden çözer.
Rota Ağacı
Adreslerin yolu zaten hiyerarşiktir. /istasyon/kuzey-yamac/olcum üç dilimden oluşur ve
her dilim bir öncekinin içini daraltır. Rota tanımını da aynı biçimde iç içe yazmak
mümkündür: her düğüm bir dilim üstlenir ve kendi altındaki düğümlere kalan dilimleri
devreder.
Ağaçtaki düğümler iki işe yarar. Düzen bileşeni olan düğüm, kendi altındaki her görünümün çevresini kurar: başlık, gezinme, çerçeve. Yaprak düğüm ise ekranın değişen bölümünü doldurur. Düzen bileşeni, alt görünümün nereye yerleşeceğini bir alt görünüm yuvası ile bildirir. Bu, Web Bileşenleri konusundaki Şablonlar ve Yuvalar dersinde tanımlanan yuva kavramının yönlendirmedeki karşılığıdır: içerik dışarıdan gelir, kap onu nereye koyacağını söyler.
Bir düğümün kendi yolu göreli yazılır. :kimlik düğümü istasyon düğümünün altında
durduğu için tam yolu /istasyon/:kimlik olur; tanımda bu ön ek yinelenmez. Böylece bir
alt ağaç tümüyle başka bir yere taşındığında içindeki tanımlar değişmez.
Üçüncü bir düğüm türü gerekir. /istasyon yolu istendiğinde IstasyonKabugu düzeni
eşleşir, ama yuvaya konacak bir alt görünüm yoktur. Bu boşluğu dizin rotası doldurur:
yol tüketildiğinde eşleşen, kendi dilimi olmayan çocuk. Dizin rotası düzenin varsayılan
içeriğidir.
Eşleşmeden Zincire
Ağaç üzerinde eşleşme, kökten yaprağa doğru dilim tüketerek ilerler. Sonuç tek bir bileşen değil, kökten yaprağa uzanan bir düzen zinciridir. Ekranda bu zincir içten dışa yerleşir: her bileşen bir sonrakini kendi yuvasında barındırır.
// rota-agaci.mjs — ic ice rota agacindan etkin duzen zincirinin uretilmesi const agac = { yol: "", bilesen: "Kabuk", cocuklar: [ { dizin: true, bilesen: "Karsilama" }, { yol: "oturum", bilesen: "OturumAc" }, { yol: "istasyon", bilesen: "IstasyonKabugu", cocuklar: [ { dizin: true, bilesen: "IstasyonListesi" }, { yol: "yeni", bilesen: "IstasyonFormu" }, { yol: ":kimlik", bilesen: "IstasyonKunyesi", cocuklar: [ { dizin: true, bilesen: "IstasyonOzeti" }, { yol: "olcum", bilesen: "OlcumGecmisi" }, { yol: "ayar", bilesen: "IstasyonAyarlari" }, ], }, ], }, { yol: "*", bilesen: "Bulunamadi" }, ], }; const SIRA = (d) => d.dizin ? 0 : d.yol === "*" ? 3 : d.yol.startsWith(":") ? 2 : 1; function coz(dugum, kalan, zincir, parametre) { if (dugum.dizin) return kalan.length === 0 ? { zincir: [...zincir, dugum.bilesen], parametre } : null; let tuketilen = 0, p = parametre; if (dugum.yol === "*") { p = { ...p, kalan: kalan.join("/") }; tuketilen = kalan.length; } else if (dugum.yol !== "") { if (kalan.length === 0) return null; if (dugum.yol.startsWith(":")) p = { ...p, [dugum.yol.slice(1)]: decodeURIComponent(kalan[0]) }; else if (dugum.yol !== kalan[0]) return null; tuketilen = 1; } const yeniZincir = [...zincir, dugum.bilesen]; const yeniKalan = kalan.slice(tuketilen); for (const cocuk of [...(dugum.cocuklar ?? [])].sort((a, b) => SIRA(a) - SIRA(b))) { const sonuc = coz(cocuk, yeniKalan, yeniZincir, p); if (sonuc) return sonuc; } return (dugum.cocuklar ?? []).length === 0 && yeniKalan.length === 0 ? { zincir: yeniZincir, parametre: p } : null; } const eslestir = (yol) => coz(agac, yol.split("/").filter(Boolean), [], {}); const yollar = ["/", "/oturum", "/istasyon", "/istasyon/yeni", "/istasyon/kuzey-yamac", "/istasyon/kuzey-yamac/olcum", "/istasyon/kuzey-yamac/ayar", "/rapor/2024"]; console.log("-- etkin duzen zinciri --"); for (const yol of yollar) { const { zincir, parametre } = eslestir(yol); console.log(yol.padEnd(30), zincir.join(" > ").padEnd(52), JSON.stringify(parametre)); } console.log("-- gezinmede korunan ve degisen --"); const gecisler = [ ["/istasyon", "/istasyon/kuzey-yamac"], ["/istasyon/kuzey-yamac", "/istasyon/kuzey-yamac/olcum"], ["/istasyon/kuzey-yamac/olcum", "/istasyon/kuzey-yamac/ayar"], ["/istasyon/kuzey-yamac/olcum", "/istasyon/dogu-sirt/olcum"], ["/istasyon/kuzey-yamac/olcum", "/oturum"], ]; for (const [onceki, sonraki] of gecisler) { const a = eslestir(onceki), b = eslestir(sonraki); let ortak = 0; while (ortak < a.zincir.length && ortak < b.zincir.length && a.zincir[ortak] === b.zincir[ortak]) ortak += 1; const parametreAyni = JSON.stringify(a.parametre) === JSON.stringify(b.parametre); console.log( `${onceki} -> ${sonraki}`.padEnd(58), "korunan:", String(ortak), "| degisen:", (b.zincir.slice(ortak).join(" > ") || "-").padEnd(24), "| parametre ayni:", parametreAyni, ); }
-- etkin duzen zinciri --
/ Kabuk > Karsilama {}
/oturum Kabuk > OturumAc {}
/istasyon Kabuk > IstasyonKabugu > IstasyonListesi {}
/istasyon/yeni Kabuk > IstasyonKabugu > IstasyonFormu {}
/istasyon/kuzey-yamac Kabuk > IstasyonKabugu > IstasyonKunyesi > IstasyonOzeti {"kimlik":"kuzey-yamac"}
/istasyon/kuzey-yamac/olcum Kabuk > IstasyonKabugu > IstasyonKunyesi > OlcumGecmisi {"kimlik":"kuzey-yamac"}
/istasyon/kuzey-yamac/ayar Kabuk > IstasyonKabugu > IstasyonKunyesi > IstasyonAyarlari {"kimlik":"kuzey-yamac"}
/rapor/2024 Kabuk > Bulunamadi {"kalan":"rapor/2024"}
-- gezinmede korunan ve degisen --
/istasyon -> /istasyon/kuzey-yamac korunan: 2 | degisen: IstasyonKunyesi > IstasyonOzeti | parametre ayni: false
/istasyon/kuzey-yamac -> /istasyon/kuzey-yamac/olcum korunan: 3 | degisen: OlcumGecmisi | parametre ayni: true
/istasyon/kuzey-yamac/olcum -> /istasyon/kuzey-yamac/ayar korunan: 3 | degisen: IstasyonAyarlari | parametre ayni: true
/istasyon/kuzey-yamac/olcum -> /istasyon/dogu-sirt/olcum korunan: 4 | degisen: - | parametre ayni: false
/istasyon/kuzey-yamac/olcum -> /oturum korunan: 1 | degisen: OturumAc | parametre ayni: false
Kök düğümün kendi yolu boştur; hiçbir dilim tüketmez ama zincirin başında durur. Bu, tüm
uygulamayı saran kabuğun tanımıdır. Parametre ağacın tek bir düğümünde çıkarılır ve o
düğümün altındaki her görünüme aynı değerle ulaşır: ölçüm geçmişi de, istasyon ayarları da
kimlik değerini yeniden çözümlemez.
Gezinmede Ne Korunur
Çıktının ikinci bölümü iç içe rotanın asıl kazancını sayıyla gösterir. İki zincirin ortak ön eki, gezinmede yerinde kalan bileşenlerdir; ondan sonrası değişir.
Ölçüm geçmişinden istasyon ayarlarına geçişte üç bileşen korunur. Kabuk, istasyon kabuğu ve istasyon künyesi ağaçta yerinde durur; yalnızca en içteki yuva yeni içerikle dolar. Yeniden çizilmedikleri için içlerindeki durum da yaşamaya devam eder: açık yan gezinme açık kalır, künyedeki veri yeniden istenmez.
Oturum açma ekranına geçişte korunan bileşen sayısı bire düşer. Zincirin geri kalanı sökülür; sökülen bileşenlerin yerel durumu kaybolur. Bu, iç içe rota tanımının bir yan etkisi değil, doğrudan ifade ettiği karardır: hangi bölümün hangi gezinmelerde yaşayacağı ağacın biçimiyle belirlenir.
Dördüncü satır tek başına bir tuzağı gösterir. kuzey-yamac istasyonundan dogu-sirt
istasyonuna geçildiğinde düzen zinciri birebir aynıdır — dört bileşenin dördü de
korunur — ama parametre değişmiştir. Bileşenler yerinde kaldığı için yeniden kurulmazlar;
ekranda hâlâ önceki istasyonun verisi durur. Doğru davranış, parametreye bağlı verinin
parametre değişimini de dinlemesidir. Bu, Bileşen Tabanlı Arayüz Geliştirme kursundaki yan
etki dersinin bağımlılık kuralının yönlendirmedeki karşılığıdır: veri isteğinin bağımlılığı
bileşenin varlığı değil, parametrenin değeridir.
Bulunamadı Rotasının Yeri
Ağaçta joker düğümü hangi düzeyde durursa, bulunamadı görünümü o düzeyin kabuğu içinde
görünür. Örnekteki joker kökün çocuğudur; /rapor/2024 isteğinde zincir kabuk ile
bulunamadı görünümünden oluşur, yani kullanıcı üst başlığı ve gezinmeyi görmeye devam eder.
Joker istasyon düğümünün altına konsaydı /istasyon/kuzey-yamac/bilinmeyen yolu istasyon
kabuğunun içinde bir hata gösterirdi; kullanıcı istasyon bağlamını kaybetmezdi. İkisi de
geçerli tasarımlardır ve seçim kullanıcının nereye dönebilmesi gerektiğine bağlıdır. Yanlış
olan tek şey, jokeri hiç tanımlamamaktır: o durumda tanımsız adres boş bir ekran üretir.
Sunucu tarafındaki karşılığı unutulmamalıdır. Bulunamadı görünümünü istemcinin çizmesi, sunucunun o adrese başarılı yanıt vermesi anlamına gelmez; Geçmiş ve Konum dersinde kurulan kural gereği gerçekten bulunmayan adres yine bulunamadı durum kodunu almalıdır.
Yolsuz Düzen Düğümleri
Ağaçtaki her düzen bir dilim tüketmek zorunda değildir. Kendi yolu boş olan bir düğüm, adresi değiştirmeden yalnızca bir çerçeve ekler. Bunun iki kullanımı vardır.
Birincisi görsel gruplamadır: birkaç rota aynı dar sütun düzenini paylaşıyorsa, o düzen adres hiyerarşisine yeni bir dilim eklemeden ortak bir üst düğüme çıkarılır. Kullanıcının gördüğü adres sadeleşmiş kalır.
İkincisi davranış paylaşımıdır: aynı erişim koşulunu ya da aynı veri yüklemesini paylaşan rotalar yolsuz bir düğümün altında toplanır. Erişim koşulunun bu düğümlerde nasıl işletileceği sonraki iki dersin konusudur.
Karşı yönde bir seçenek daha vardır: bir dilim tüketen ama kendi görünümü olmayan düğüm. Bu düğüm adres hiyerarşisini derinleştirir, ekrana bir şey eklemez; alt görünüm doğrudan üst yuvaya yerleşir.
Özet
- Rota ağacı, adresin hiyerarşisini rota tanımının hiyerarşisine çevirir; her düğüm bir dilim üstlenir ve alt yolları çocuklarına devreder.
- Düzen bileşeni alt görünümü bir yuvada barındırır; dizin rotası, yol tüketildiğinde düzenin varsayılan içeriğini sağlar.
- Eşleşmenin çıktısı tek bileşen değil, kökten yaprağa uzanan bir düzen zinciridir; parametre ağaçta bir kez çıkarılır ve altındaki tüm görünümlere ulaşır.
- Gezinmede iki zincirin ortak ön eki yerinde kalır ve içindeki durum korunur; ayrılan bölüm sökülüp yeniden kurulur.
- Zincir aynı kalıp yalnız parametre değiştiğinde bileşenler yeniden kurulmaz; parametreye bağlı verinin bu değişimi kendi bağımlılığı olarak izlemesi gerekir.
- Joker düğümünün ağaçtaki düzeyi, bulunamadı görünümünün hangi kabuğun içinde görüneceğini belirler.
Sonraki Adım
Ağaç, yolun taşıdığı durumu — hangi istasyon, hangi bölüm — bileşenlere ulaştırdı. Ekranın geri kalan durumu ise henüz adreste değil. Ölçüm geçmişi sayfasında bir tarih aralığı seçili, bir ölçüm türü süzülmüş, liste ikinci sayfada ve tarihe göre azalan sıralanmış olabilir. Bunlar bileşenin yerel değişkenlerinde tutulduğunda kullanıcı o görünümü paylaşamaz, yer imine ekleyemez ve geri düğmesiyle önceki süzgece dönemez. Sonraki ders hangi durumun yola, hangisinin sorguya yazılacağını, sorgu durumunun nasıl serileştirilip geri çözümleneceğini ve varsayılan değerlerin adresi nasıl kirletmeden bırakılacağını ele alır.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.