Ders 23 / 23
Biçem Başarımı
Seçici eşleştirmenin sağdan sola yapılması, geçersiz kılma kapsamının seçici biçimine bağlılığı, biçem dosyasının çizimi engellemesi ve kritik biçem alt kümesinin hesaplanması.
İçindekiler
Önceki beş ders biçemin nasıl düzenleneceğini ele aldı ve her biri aynı soruyu farklı yerden yanıtladı. Bir soru daha var ve onu tarayıcı sorar.
Biçem dosyası indirilir, ayrıştırılır, her ögeye hangi kuralların uyduğu bulunur ve hesaplanmış değerler üretilir. Bu işin bir maliyeti vardır ve maliyetin nereden geldiği, yazım kararlarını da etkiler. Bu ders o maliyeti kural olarak kurar ve kursu kapatır.
Eşleştirme Sağdan Sola Yapılır
Bir seçicinin bir ögeye uyup uymadığı sorusu iki yönde yanıtlanabilir. Soldan sağa gitmek — önce en dıştaki seçiciyi bulup alt ağaçta ilerlemek — okuma yönüne uyar. Tarayıcılar bunu yapmaz; sağdan sola gider.
Nedeni şudur: soru “bu seçici hangi ögelere uyar” değil, “bu ögeye hangi kurallar uyar”dır. Öge elde olduğunda, seçicinin en sağdaki bileşeni — anahtar seçici — ögeye uymuyorsa kural hemen elenir. Uyuyorsa atalara doğru yürünür.
// bicembasarim.mjs — secici eslestirme yonu ve kritik bicem alt kumesinin hesaplanmasi // --- kucuk bir belge agaci --- const yap = (tur, siniflar, cocuk = []) => ({ tur, siniflar, cocuk, ust: null }); const BELGE = yap("body", [], [ yap("header", ["kunye"], [ yap("h1", ["kunye__ad"]), yap("p", ["kunye__konum"]), yap("nav", ["gezinme"], [yap("ul", [], [yap("li", [], [yap("a", ["etkin"])]), yap("li", [], [yap("a", [])])])]), ]), yap("main", [], [ yap("section", ["olcum-bolumu"], [ yap("h2", ["baslik"]), yap("div", ["olcum-kartlari"], [ yap("article", ["olcum-kart"], [yap("h3", ["olcum-kart__baslik"]), yap("p", ["olcum-kart__deger"])]), yap("article", ["olcum-kart"], [yap("h3", ["olcum-kart__baslik"]), yap("p", ["olcum-kart__deger"])]), yap("article", ["olcum-kart", "olcum-kart--genis"], [yap("h3", ["olcum-kart__baslik"]), yap("p", ["olcum-kart__deger"])]), ]), ]), yap("section", ["konum-bolumu"], [yap("h2", ["baslik"]), yap("p", []), yap("p", [])]), ]), yap("footer", ["kaynak-notu"], [yap("p", [])]), ]); function bagla(dugum, ust = null) { dugum.ust = ust; for (const c of dugum.cocuk) bagla(c, dugum); return dugum; } bagla(BELGE); const tumu = (d, liste = []) => { liste.push(d); for (const c of d.cocuk) tumu(c, liste); return liste; }; const DUGUMLER = tumu(BELGE); // --- bilesik secici denetimi (tur ve sinif) --- let denetim = 0; function uyar(dugum, bilesik) { denetim++; const tur = bilesik.match(/^[a-z][\w-]*/); if (tur && dugum.tur !== tur[0]) return false; for (const s of bilesik.match(/\.[\w-]+/g) || []) if (!dugum.siniflar.includes(s.slice(1))) return false; return true; } // sagdan sola: once anahtar secici, sonra atalar function sagdanSola(secici) { const p = secici.trim().split(/\s+/); denetim = 0; let eslesen = 0; for (const d of DUGUMLER) { if (!uyar(d, p[p.length - 1])) continue; let i = p.length - 2, ata = d.ust, tamam = i < 0; while (i >= 0 && ata) { if (uyar(ata, p[i])) i--; ata = ata.ust; if (i < 0) tamam = true; } if (tamam) eslesen++; } return { denetim, eslesen }; } // soldan saga: once ilk secici, sonra alt agaclarda ilerle function soldanSaga(secici) { const p = secici.trim().split(/\s+/); denetim = 0; let eslesen = 0; const ilerle = (dugum, i) => { for (const c of tumu(dugum).slice(1)) { if (!uyar(c, p[i])) continue; if (i === p.length - 1) eslesen++; else ilerle(c, i + 1); } }; for (const d of DUGUMLER) { if (!uyar(d, p[0])) continue; if (p.length === 1) eslesen++; else ilerle(d, 1); } return { denetim, eslesen }; } console.log(`belgedeki dugum sayisi: ${DUGUMLER.length}`); console.log("\n--- ayni seciciyi iki yonde eslestirmenin denetim sayisi ---"); console.log("secici".padEnd(62) + "sagdan sola".padStart(13) + "soldan saga".padStart(13) + " eslesen"); for (const s of [ ".olcum-kart__baslik", ".olcum-bolumu .olcum-kartlari .olcum-kart .olcum-kart__baslik", "body main section div article h3", ".kunye__ad", ]) { const sa = sagdanSola(s), so = soldanSaga(s); console.log(s.padEnd(62) + String(sa.denetim).padStart(13) + String(so.denetim).padStart(13) + String(sa.eslesen).padStart(10)); } // --- kritik bicem: ilk ekranda gorunen ogelere uyan kurallar --- const KURALLAR = [ { secici: ".kunye", bayt: 96 }, { secici: ".kunye__ad", bayt: 64 }, { secici: ".gezinme", bayt: 88 }, { secici: ".gezinme a", bayt: 72 }, { secici: ".olcum-kartlari", bayt: 120 }, { secici: ".olcum-kart", bayt: 148 }, { secici: ".olcum-kart__baslik", bayt: 58 }, { secici: ".olcum-kart__deger", bayt: 86 }, { secici: ".olcum-kart--genis", bayt: 44 }, { secici: ".konum-bolumu", bayt: 92 }, { secici: ".konum-bolumu p", bayt: 60 }, { secici: ".kaynak-notu", bayt: 54 }, { secici: ".olcum-suzgeci", bayt: 132 }, { secici: ".yan-bilgi", bayt: 104 }, ]; // Ilk ekranda gorunen bolum: kunye ve olcum bolumu (belge sirasinda ilk 20 dugum). const GORUNUR = new Set(DUGUMLER.slice(0, 20)); const uyanVar = (secici) => { const p = secici.trim().split(/\s+/); return [...GORUNUR].some((d) => { if (!uyar(d, p[p.length - 1])) return false; let i = p.length - 2, ata = d.ust; while (i >= 0 && ata) { if (uyar(ata, p[i])) i--; ata = ata.ust; } return i < 0; }); }; const kritik = KURALLAR.filter((k) => uyanVar(k.secici)); const toplam = KURALLAR.reduce((t, k) => t + k.bayt, 0); const kritikBayt = kritik.reduce((t, k) => t + k.bayt, 0); console.log("\n--- kritik bicem alt kumesi ---"); console.log(` ilk ekranda gorunen dugum sayisi: ${GORUNUR.size} / ${DUGUMLER.length}`); console.log(` kritik kural: ${kritik.length} / ${KURALLAR.length}`); console.log(` kritik bayt : ${kritikBayt} / ${toplam} (%${((kritikBayt / toplam) * 100).toFixed(1)})`); console.log(" kritik olmayanlar:", KURALLAR.filter((k) => !kritik.includes(k)).map((k) => k.secici).join(", "));
belgedeki dugum sayisi: 29 --- ayni seciciyi iki yonde eslestirmenin denetim sayisi --- secici sagdan sola soldan saga eslesen .olcum-kart__baslik 29 29 3 .olcum-bolumu .olcum-kartlari .olcum-kart .olcum-kart__baslik 38 55 3 body main section div article h3 44 102 3 .kunye__ad 29 29 1 --- kritik bicem alt kumesi --- ilk ekranda gorunen dugum sayisi: 20 / 29 kritik kural: 8 / 14 kritik bayt : 732 / 1218 (%60.1) kritik olmayanlar: .olcum-kart--genis, .konum-bolumu, .konum-bolumu p, .kaynak-notu, .olcum-suzgeci, .yan-bilgi
Yirmi dokuz düğümlük bir belgede dört seçici deneniyor. Tek sınıflı seçicilerde iki yön aynı sayıda denetim yapıyor: her düğüm bir kez sınanıyor.
Ayrım uzun seçicilerde çıkıyor. Dört bileşenli seçici sağdan sola 38, soldan sağa 55 denetim istiyor; altı bileşenli tür seçicisi zinciri 44’e karşı 102. Sağdan sola yürüyüş, anahtar seçici uymayan düğümleri tek denetimde eliyor; soldan sağa yürüyüş her uyan başlangıç için alt ağacın tamamını geziyor.
Buradan çıkan yazım kuralı, anahtar seçicinin ayırıcı olmasıdır. ... h3 biçiminde biten
bir seçici, belgedeki bütün başlıklarda ata yürüyüşü başlatır; ... .olcum-kart__baslik
biçiminde biten seçici yalnız üç düğümde başlatır.
Bir ölçü duygusu gerekir: seçici eşleştirme, yerleşim ve boyama aşamalarının yanında küçük bir maliyettir. Uzun seçicilerin asıl bedeli eşleştirme sayısı değil, bir sonraki bölümdeki geçersiz kılma kapsamıdır.
Geçersiz Kılma Kapsamı
Bir ögenin sınıfı değiştiğinde, tarayıcı hangi ögelerin biçeminin yeniden hesaplanacağını belirlemek zorundadır. Bu kümeye geçersiz kılma kapsamı (invalidation scope) denir ve seçicilerin biçiminden çıkarılır.
Kural şudur: bir sınıf yalnız kendi ögesine uyan kurallarda geçiyorsa kapsam o ögedir. Aynı sınıf bir alt öge birleştiricisinin solunda geçiyorsa, kapsam ögenin bütün alt ağacıdır.
.olcum-kart--uyari { border-color: var(--uyari); } /* kapsam: ögenin kendisi */ .olcum-kart--uyari .olcum-kart__deger { color: var(--uyari); } /* kapsam: alt ağacın tamamı */
İkinci yazımda karta sınıf eklemek, kartın içindeki bütün ögelerin biçemini yeniden hesaplatır. Önceki derste kurulan özel özellik yazımı bu maliyeti de düşürür: değiştirici yalnız bir değer yazar, alt ögeler zaten o değeri okuyordur.
Ata yönünde çalışan seçiciler kapsamı yukarı doğru genişletir: bir ögenin durumunun ana ögesini de etkilediği yazımlarda, değişimin sonucu ağacın üst kısmına taşınır. Bu tür seçiciler güçlüdür ve gerektiğinde kullanılır; ölçüsüz kullanıldığında geçersiz kılma kapsamını öngörülemez kılar.
Biçem Dosyası Çizimi Engeller
Bir belgenin ilk çizimi, biçem dosyası indirilip ayrıştırılana kadar bekler. Bunun nedeni belirlidir: biçem bilinmeden çizilen sayfa, biçem geldiğinde baştan çizilir ve kullanıcı biçimsiz bir sayfa görür.
Üç sonucu vardır. Biçem dosyası belgenin baş kısmında bildirilir; sonda bildirilmesi
ayrıştırmanın ilerlemesini geciktirir. media özniteliği taşıyan ve koşulu sağlanmayan bir
dosya çizimi engellemez; yazdırma biçemi bu yolla ayrılır. Biçem dosyasının içinden başka bir
dosya çağıran @import kuralı ise iki indirmeyi sıraya sokar; ikinci istek ancak birinci
dosya ayrıştırıldıktan sonra başlar.
Kritik Biçem
İlk çizim için gereken kurallar, dosyadaki kuralların tamamı değildir. Yalnız ilk ekranda görünen ögelere uyan kurallar gerekir; kalanlar sonra yüklenebilir.
Çıktının ikinci bloğu bu alt kümeyi hesaplıyor: yirmi dokuz düğümün ilk yirmisi görünür kabul edildiğinde, on dört kuralın sekizi gerekli çıkıyor. Bayt olarak toplamın yüzde 60’ı.
Kritik alt küme belgenin içine doğrudan yazılır; kalan kurallar çizimi engellemeyen bir biçimde yüklenir. Bu yazımın iki bedeli vardır. Birincisi yinelemedir: kritik kurallar hem belgenin içinde hem dosyada bulunur. İkincisi bayatlamadır; sayfa yapısı değiştiğinde kritik küme yeniden hesaplanmalıdır, elle bakımı sürdürülemez.
Bu yüzden kritik biçem, elle yazılan değil üretilen bir çıktıdır — hesabı yukarıdaki kadar mekaniktir: görünür öge kümesi ve kural listesi verildiğinde alt küme belirlidir.
Katmanlar ve Bakım Maliyeti
@layer kuralının çalışma zamanı maliyeti küçüktür ama bir sıra kuralı vardır: katman
sırası, katman adlarının ilk göründüğü yerde belirlenir. Bu yüzden katman adları biçem
dosyasının başında tek satırda bildirilir:
@layer taban, duzen, bilesen, yardimci;
Bu satır sıraları sabitler; hangi dosyanın hangi sırada yüklendiği artık sonucu değiştirmez.
Kazandırdığı şey bir başarım ölçüsü değil, ölçülemeyen bir maliyetin — özgüllük tırmanışının
ve !important zincirlerinin — önüne geçmesidir.
Yardımcı sınıflar en üst katmanda durur; böylece tek bildirimlik bir sınıf, bileşen kuralını özgüllük hilesi olmadan ezebilir. Bu, beşinci dersteki karma kullanımın gerçekten çalışması için gereken düzenlemedir.
Özet
- Seçici eşleştirme sağdan sola yapılır; anahtar seçici uymayan düğümler tek denetimde elenir, bu yüzden ayırıcı bir anahtar seçici uzun seçicileri de ucuzlatır.
- Uzun seçicilerin asıl bedeli eşleştirme sayısı değil geçersiz kılma kapsamıdır: bir sınıf alt öge birleştiricisinin solunda geçiyorsa kapsam bütün alt ağaçtır.
- Biçem dosyası ilk çizimi engeller; koşulu sağlanmayan
mediabildirimi engellemez,@importise indirmeleri sıraya sokar. - Kritik biçem, ilk ekranda görünen ögelere uyan kuralların alt kümesidir; hesabı mekaniktir ve elle bakımı sürdürülemediği için üretilmelidir.
- Katman sırası adların ilk göründüğü yerde belirlenir; başta tek satırla bildirmek yükleme sırasını sonuçtan bağımsız kılar.
Kurs Kapanışı
Bu kurs düzenle başladı. Esnek kutu tek eksende boş alanı bölüştürdü, ızgara iki eksende hat tanımladı ve ikisi arasındaki seçim bir ölçüte bağlandı. Duyarlı tasarım, kesme noktalarını aygıt listelerinden değil içeriğin kendisinden türetti; ortam sorguları görüntü alanını, kapsayıcı sorguları bileşenin kendi bağlamını sordu ve kullanıcı tercihleri tasarımın girdisi oldu.
Hareket konusu geometriyi ve zamanı ayırdı: dönüşüm matrisi neyin nereye taşındığını, zamanlama eğrisi bunun ne kadar sürede olduğunu belirledi. Çizim hattı hangi bildirimin hangi aşamayı çalıştırdığını gösterdi ve hareketin bir de kullanıcıya çıkan maliyeti olduğu görüldü.
Son konu ise bütün bunların nereye yazılacağını sordu. Adlandırma yöntemi özgüllüğü düz tuttu, özel özellikler bileşene bir arayüz verdi, derleme araçları kaynağı düzenledi, kapsamlama adları sözleşmeden mekanizmaya taşıdı ve yardımcı sınıflar kısıtı sistemin kendisine gömdü. Kuzey Yamaç Ölçüm İstasyonu sayfası bu derslerin her birinde bir adım daha ilerledi ve sonunda bileşen dosyalarına, bir ölçek tanımına ve katman sırasına bölünmüş bir biçem katmanına kavuştu.
Sayfanın hâlâ yapamadığı bir şey var: kendisi hiçbir şey yapmıyor. Ölçüm kartları belgede yazılı olduğu için görünüyor, durum göstergesi bir öznitelik elle değiştirildiğinde değişiyor, süzgeç hiçbir şeyi süzmüyor. Belge ağacının programla değiştirilmesi, kullanıcı eylemlerinin olay olarak yakalanması ve tarayıcının sunduğu arayüzlerin kullanılması bir sonraki kursun konusudur: Tarayıcı ve Web Platformu. Orada belge, bir biçim verilmiş metin olmaktan çıkıp üzerinde çalışılan bir veri yapısına dönüşür.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.