İçeriğe geç
academia.sh

Ders 01 / 22

İstemci Tarafı Yönlendirme

Adresi görünüme çeviren katman; rota tablosu, yol kalıplarının çözümlenmesi, özgüllüğe göre sıralama, parametre çıkarımı, bağlantı kesme ve gezinme döngüsünün sorumlulukları.

İçindekiler

Önceki kurs bileşeni ve bileşimi kurdu: girdisi olan, kendi yerel durumunu tutan, başka bileşenlerin içine yerleşen bir birim. Bileşen ağacı bir kez kurulduğunda hangi verinin nereye aktığı bellidir. Belirsiz kalan soru bir üst katmandadır: ağacın kökünde hangi bileşen duracak? Kuzey Yamaç Ölçüm İstasyonu uygulaması artık tek ekran değil. İstasyon listesi, istasyon ayrıntısı, ölçüm geçmişi ve oturum açma ekranı var; bunlardan hangisinin görüneceğine bir yerde karar verilmelidir.

Bu kararın kaynağı adrestir. Tarayıcı ve Web Platformu kursundaki Geçmiş ve Konum dersinde adresin parçalara ayrılabildiği, geçmiş yığıtının program tarafından değiştirilebildiği ve gezinmenin sayfa yeniden yüklenmeden yapılabildiği kurulmuştu. Yönlendirme, o düzeneğin üzerine oturan karar katmanıdır: adresi alır, hangi görünümün kurulacağını söyler.

Yönlendirmenin Tanımı

Yönlendirme (routing), bir adresi bir görünüme eşleyen işlemdir. Girdisi adresin yol bölümü, çıktısı iki parçadır: görüntülenecek bileşen ve o bileşene verilecek parametreler.

Sunucu tarafında bu iş zaten yapılır; her istek bir yola bakılarak yanıtlanır. İstemci tarafı yönlendirmenin farkı, kararın belge yeniden yüklenmeden verilmesidir. Kullanıcı istasyon listesindeki bir satıra tıkladığında yeni bir belge istenmez; adres değişir, eşleyici yeni yolu çözümler, ağacın bir bölümü yeni bileşenle değiştirilir.

Bunun kazancı gezinme maliyetinin düşmesi değildir yalnızca. Belge yerinde kaldığı için bellekteki durum korunur: yarım kalan bir form, açık bir panel, indirilmiş bir veri kümesi gezinmeden sonra da durur. Bedeli, tarayıcının kendiliğinden yaptığı işlerin sayfanın sorumluluğuna geçmesidir — kaydırma konumu, odak yönetimi, isteklerin iptali, sekme başlığı. Bunların hepsi bu konu boyunca tek tek ele alınır.

Rota Tablosu

Yönlendirmenin verisi bir rota tablosudur: yol kalıbı ile görünüm eşlemelerinin listesi. Yol kalıbı sabit dilimlerden, parametre dilimlerinden ve jokerden oluşur.

/istasyon sabit bir dilimdir; yalnızca kendisiyle eşleşir. /:kimlik bir parametre dilimidir; herhangi bir dilimle eşleşir ve eşleştiği değeri bir ada bağlar. /* jokerdir; kalan dilimlerin tümünü tüketir ve genellikle “bulunamadı” görünümüne bağlanır.

Tablonun tek başına yeterli olmadığı bir nokta vardır. /istasyon/yeni yolu iki kalıba birden uyar: hem /istasyon/yeni sabitine, hem /istasyon/:kimlik parametresine. Hangisi kazanır? Yanıt yazım sırası olamaz — o zaman tablodaki satırların yeri anlam taşır ve iki geliştirici sıralamayı bozduğunda hata sessizce ortaya çıkar. Yanıt özgüllüktür: daha az yolu kabul eden kalıp önce denenir.

// rota-eslestirici.mjs — yol kalibinin cozumlenmesi, ozgullukle siralama, parametre cikarimi
const AGIRLIK = { sabit: 3, parametre: 2, joker: 1 };

function kalibiCozumle(kalip) {
  const parcalar = kalip.split("/").filter(Boolean).map((p) =>
    p === "*" ? { tur: "joker" }
      : p.startsWith(":") ? { tur: "parametre", ad: p.slice(1) }
        : { tur: "sabit", deger: p });
  return {
    kalip, parcalar,
    skor: parcalar.map((p) => AGIRLIK[p.tur]),
    joker: parcalar.some((p) => p.tur === "joker") ? 1 : 0,
  };
}

function ozgullukKarsilastir(a, b) {
  if (a.joker !== b.joker) return a.joker - b.joker;      // jokerli kalip en sona
  const ortak = Math.min(a.skor.length, b.skor.length);
  for (let i = 0; i < ortak; i++)                         // ilk farkli dilim karari verir
    if (a.skor[i] !== b.skor[i]) return b.skor[i] - a.skor[i];
  return b.skor.length - a.skor.length;                   // uzun kalip once
}

function eslestir(rota, yol) {
  const dilim = yol.split("/").filter(Boolean);
  const parametre = {};
  for (let i = 0; i < rota.parcalar.length; i++) {
    const p = rota.parcalar[i];
    if (p.tur === "joker") { parametre.kalan = dilim.slice(i).join("/"); return parametre; }
    if (i >= dilim.length) return null;
    if (p.tur === "sabit") { if (p.deger !== dilim[i]) return null; }
    else parametre[p.ad] = decodeURIComponent(dilim[i]);
  }
  return dilim.length === rota.parcalar.length ? parametre : null;
}

// Yazim sirasi bilerek bozuk: ":kimlik" daha genel oldugu halde "yeni"den once yazildi.
const yazimSirasi = [
  "/istasyon/:kimlik",
  "/istasyon/yeni",
  "/*",
  "/istasyon/:kimlik/olcum/:zaman",
  "/",
  "/istasyon",
  "/istasyon/:kimlik/olcum",
];
const tablo = yazimSirasi.map(kalibiCozumle).sort(ozgullukKarsilastir);

console.log("-- ozgulluge gore siralanmis tablo --");
for (const r of tablo) console.log((r.skor.join(",") || "-").padEnd(9), r.kalip);

console.log("-- eslesme --");
for (const yol of ["/", "/istasyon", "/istasyon/yeni", "/istasyon/kuzey-yamac",
  "/istasyon/kuzey-yamac/olcum", "/istasyon/kuzey-yamac/olcum/2024-02-11T06:00",
  "/istasyon/kuzey%20yamac", "/ayarlar/gizlilik"]) {
  let bulunan = null, parametre = null;
  for (const r of tablo) {
    const p = eslestir(r, yol);
    if (p) { bulunan = r.kalip; parametre = p; break; }
  }
  console.log(yol.padEnd(44), bulunan.padEnd(30), JSON.stringify(parametre));
}
-- ozgulluge gore siralanmis tablo --
3,3       /istasyon/yeni
3,2,3,2   /istasyon/:kimlik/olcum/:zaman
3,2,3     /istasyon/:kimlik/olcum
3,2       /istasyon/:kimlik
3         /istasyon
-         /
1         /*
-- eslesme --
/                                            /                              {}
/istasyon                                    /istasyon                      {}
/istasyon/yeni                               /istasyon/yeni                 {}
/istasyon/kuzey-yamac                        /istasyon/:kimlik              {"kimlik":"kuzey-yamac"}
/istasyon/kuzey-yamac/olcum                  /istasyon/:kimlik/olcum        {"kimlik":"kuzey-yamac"}
/istasyon/kuzey-yamac/olcum/2024-02-11T06:00 /istasyon/:kimlik/olcum/:zaman {"kimlik":"kuzey-yamac","zaman":"2024-02-11T06:00"}
/istasyon/kuzey%20yamac                      /istasyon/:kimlik              {"kimlik":"kuzey yamac"}
/ayarlar/gizlilik                            /*                             {"kalan":"ayarlar/gizlilik"}

Sıralama, yazım sırasından bağımsız bir düzen üretmiştir. /istasyon/yeni en başa çıkmıştır; /istasyon/kuzey-yamac yolu ona uymadığı için parametreli kalıba düşer ve kimlik doğru çıkarılır. Joker en sona alındığı için hiçbir gerçek rotayı gölgelemez.

Eşleşme tablosunda üç ayrıntı daha okunur. Kök yolun kalıbı hiç dilim içermez ve yalnız kendisiyle eşleşir. Parametre değeri, adresteki kaçırma çözülerek verilir: kuzey%20yamac dilimi kuzey yamac olur; bunu yapmayan bir eşleyici, boşluk veya Türkçe karakter içeren kimlikleri bozuk teslim eder. Tanımsız yol jokere düşer ve kalan alanında ne istendiğini taşır; bulunamadı görünümü bu bilgiyi kullanıcıya gösterebilir.

Bir kural da örtük olarak kuruludur: parametre dilimi bir dilim tüketir. /istasyon/a/b yolu /istasyon/:kimlik kalıbına uymaz, çünkü dilim sayıları tutmaz. Eğik çizgi içeren bir değer taşınacaksa ya joker kullanılır ya da değer kaçırılarak tek dilime sığdırılır.

Gezinme Döngüsü

Eşleyici bir işlevdir; yönlendirme ise sürekli çalışan bir döngüdür. Döngünün dört adımı vardır ve her adımın ayrı bir sorumluluğu bulunur.

Adres değişir. Bunun üç kaynağı vardır: kullanıcının bir bağlantıya tıklaması, programın gezinme çağırması, kullanıcının geri veya ileri düğmesine basması. İlk ikisinde adresi kod değiştirir; üçüncüsünde tarayıcı değiştirir ve koda haber verir.

Eşleyici çalışır. Yeni yol rota tablosunda aranır, kazanan kalıp ve parametreler çıkarılır.

Görünüm kurulur. Kazanan rotanın bileşeni ağaca yerleştirilir, parametreler ona verilir.

Kenar sorumluluklar yerine getirilir. Kaydırma konumu ayarlanır, odak yeni içeriğe taşınır, sekme başlığı güncellenir, önceki görünümün istekleri iptal edilir.

Döngünün en çok atlanan yeri dördüncü adımdır. Gerçek gezinmede tarayıcı bunları kendiliğinden yapar; istemci tarafı gezinmede belge değişmediği için hiçbiri olmaz. Odağın taşınmaması özellikle sessiz bir kusurdur: klavye veya ekran okuyucu kullanan biri bağlantıya bastığında sayfanın değiştiğini fark etmez, odak eski konumunda kalır.

Bağlantıyı Kesmek

İstemci tarafı gezinmenin başlangıcı, bağlantı tıklamasının varsayılan eylemini iptal etmektir. Belge ve Olaylar konusundaki Varsayılan Davranış ve İptal dersinde bu düzenek kurulmuştu: olay iptal edilebilir olduğunda tarayıcının kendi davranışı durdurulabilir.

Her tıklama kesilmez. Kesilmemesi gereken durumlar bellidir ve bir koşul dizisiyle sınanır. Farklı bir kaynağa giden bağlantı kesilmez; uygulama o adresi zaten görüntüleyemez. İndirme başlatan bağlantı, yeni sekmede açılması istenen bağlantı ve kullanıcının değiştirici tuşla açtığı bağlantı da kesilmez. Sağ tıkla açılan menü üzerinden yapılan işlemler ise olayı hiç üretmez.

Bu koşullar unutulduğunda ortaya çıkan kusur her zaman aynıdır: kullanıcı bilinen bir tarayıcı davranışını kaybeder. Bağlantıyı yeni sekmede açamamak, adresi kopyalayamamak veya indirme bağlantısının çalışmaması, hepsi bu tek eksikten doğar.

İptal edilen tıklamanın ardından yapılacak iş, geçmişe yeni bir kayıt eklemek ve döngüyü başlatmaktır. Geri düğmesi de aynı döngüyü, kayıt eklemeden çalıştırır: tarayıcı gezinme olayını üretir, kod olayı dinler, eşleyiciyi yeni yolla çağırır.

Adresin Tek Doğru Kaynağı Olması

Yönlendirme kurulduğunda uygulamada iki ayrı “hangi ekrandayız” bilgisi bulunabilir: adres ve bir yerel değişken. İkisi ayrı tutulduğunda kaçınılmaz olarak ayrışırlar. Geri düğmesine basıldığında adres değişir ama değişken eski değerinde kalır; ya da tersi olur.

Kural şudur: etkin görünüm adresten türetilir, bellekte ayrıca tutulmaz. Bir ekrana gitmek, bir değişkeni ayarlamak değil, adresi değiştirmektir. Görünüm o değişikliğin sonucudur.

Bu kural bir sınama ölçütü verir. Uygulamanın herhangi bir ekranındayken adres çubuğundaki adres kopyalanıp yeni bir sekmede açıldığında aynı ekran gelmelidir. Gelmiyorsa, o ekranın bir bölümü adrese yazılmamış demektir.

Kuralın karşılığı sunucu tarafındadır ve Geçmiş ve Konum dersinde kurulmuştu: istemcinin ürettiği her adres doğrudan istendiğinde geçerli bir yanıt almalıdır. Tanımlı yol örüntülerini tek belgeye eşleyen bir sunucu bunu sağlar; gerçekten bulunmayan adreslerin yine bulunamadı yanıtı vermesi de aynı sözleşmenin parçasıdır.

Özet

  • Yönlendirme, adresin yol bölümünü bir görünüme ve parametre kümesine eşleyen karar katmanıdır; istemci tarafında bu karar belge yeniden yüklenmeden verilir.
  • Rota tablosu sabit, parametreli ve joker dilimlerden kurulur; eşleşme belirsizliği yazım sırasıyla değil özgüllük sıralamasıyla çözülür, joker her zaman en sona alınır.
  • Parametre dilimi tek dilim tüketir ve değeri kaçırması çözülerek verilir.
  • Gezinme bir döngüdür: adres değişir, eşleyici çalışır, görünüm kurulur, kaydırma–odak– başlık–iptal gibi kenar sorumluluklar yerine getirilir.
  • Bağlantı tıklamasının varsayılan eylemi yalnızca uygulamanın gerçekten üstlenebileceği durumlarda iptal edilir; dış adres, indirme ve yeni sekme istekleri tarayıcıya bırakılır.
  • Etkin görünüm adresten türetilir; aynı bilgiyi ayrıca bellekte tutmak geri düğmesiyle ayrışan iki doğru kaynak üretir.

Sonraki Adım

Bu dersin eşleyicisi düz bir tablo üzerinde çalıştı: her yol tek bir görünüme bağlandı. Uygulamanın ekranları ise ortak bir kabuk paylaşıyor. İstasyon ayrıntısı ile ölçüm geçmişi aynı 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 rotada yeniden kurulur, yeniden çizilir ve içindeki durum her gezinmede sıfırlanır. Sonraki ders rotaları ağaç biçiminde iç içe tanımlamayı, eşleşen dallardan bir düzen zinciri üretmeyi ve gezinmede kabuğun neden korunduğunu ele alır.

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat