Açısal Rönesans Bölüm 3: Genişletilmiş şablon sözdizimi
Angular Renaissance makale serisinin üçüncü ve son bölümü, Angular 17.0'dan itibaren geliştirici önizlemesi olarak sunulan genişletilmiş şablon sözdizimine ayrılmıştır. Bu yeni ekleme, sıvı alımı ve sinyal vermeyle karşılaştırıldığında önemsiz görünebilir.
Duyuru
Bunun bir kısmı, Angular'ın öncülük ettiği bir yenilik olan ertelenebilir görüşlerdir. Kodu bölmek, uygulamayı birden çok JavaScript dosyasına böler; bu da her şeyin hemen yüklenmediği anlamına gelir. Bu teknoloji yeni bir şey değil, ancak ertelenebilir görünümleri tanımlama, kodu doğrudan HTML'de bölme ve ayrıca çeşitli kriterlere göre benzersizdir. Angular 18'de ertelenebilir görünümler bu hafta önizleme modundan çıktı.
Rainer Hahnekamp, AngularArchitects.io uzman ağının eğitmeni ve danışmanıdır ve Angular'ın tüm yönleriyle ilgili eğitimlerden sorumludur. Ayrıca YouTube'daki ng-news ile haftalık olarak Angular ortamındaki ilgili etkinliklere kısa bir genel bakış sağlar.
Gelişmiş şablon söz dizimi
Angular her zaman HTML standardını çok yakından takip etmiş ve yalnızca istisnai durumlarda bu standarttan sapmıştır. Ancak Angular 17 ile bu uyum sona erdi.
Genişletilmiş sözdizimi olarak da adlandırılan şablon blokları, yapısal direktiflerin yerini alır *ngIf, *ngFor VE *ngSwitch Başından sonuna kadar @if, @for birlikte @switch. Bu, bir yandan sözdizimini basitleştirirken diğer yandan yapısal direktifler, dahili teknik nedenlerden dolayı artık sonraki sinyal bileşenleriyle (bkz. bölüm 2) çalışmayacaktır.
Talimatlarla @if, @for VE @switchHTML ile karıştırılan kontrol akışı doğrudan gömülür. Yani kontrol yapıları artık etiketlerin dışında.
Örneğin, Angular 17'den önce bir şablon şu şekilde görünüyordu:
<ul>
<ng-container *ngFor="let country of countries">
<li *ngIf="country.locale === filteredLocale">{{ country.name }}</li>
</ng-container>
</ul>
Yeni şablon sözdizimi artık aşağıdaki kodla sonuçlanıyor:
<ul>
@for (country of countries; track country.name) {
@if (country.locale === filteredLocale) {
<li>{{ country.name }}</li>
}
}
</ul>
Bu nedenle bir bileşen modeli, program kodu ve HTML'nin birleşiminden oluşur. React'tan bilinen JSX JavaScript sözdizimi uzantısıyla olan benzerlikler kesinlikle kasıtlıdır.
Un seçimi @karakter Svelte yapısından ilham almıştır. Burada topluluk galip geldi çünkü Angular ekibi başlangıçta farklı bir sözdizimine sahipti.
Bu değişimin kilit noktası neden sorusudur. Belki yeni sözdizimi biraz daha kullanıcı dostu görünebilir, ancak bu, kodun tamamını tekrar gözden geçirip düzenlemeniz gerektiği anlamına mı geliyor? Sebepler başka yerde yatıyor: Sözdizimi değişikliği esas olarak gelecekteki sinyal bileşeni için bir ayardır.
Angular ekibinin sinyal bileşeni için versiyon 16'dan çok önce ve hatta sinyalleri duyurmadan önce prototipleri ve planları vardı. Görünen o ki, mevcut yapısal yönergelerin uygulanmasının, sinyal bileşenlerinin çalışabilmesi için iyileştirmeler gerektirdiği ortaya çıktı.
Ayrıca Angular ekibi bu direktiflerin teknik uygulamasından pek memnun değildi. Örneğin, geliştirici deneyimi bir tane bırakıyor *ngIf arzulanan çok şey bıraktı. Kolay bir else bu biraz sözdizimsel bir zorluktur ve elseif zaten o hiçbir zaman var olmadı.
Ek olarak, kontrol akışı komutlarının her zaman açıkça içe aktarılması gerekir. Şablon bu özelliği yerel olarak desteklemiyor. Ancak bu artık modern çerçevelerde standarttır. Angular derleyicisi bununla ilgileneceği için yerel desteğin performans faydaları da olacaktır.
Dolayısıyla genişletilmiş sözdiziminin ve Angular geliştiricilerinin onu bir an önce kullanmasının önemli nedenleri var.
Örneğin yenisiyle @If daha fazla şube sorun değil:
<ul>
@for (country of countries;track country.name) {
@if (country.name === 'Austria') {
<li>Österreich</li>
} @else if (country.locale === filteredLocale) {
<li>{{ country.name }}</li>
} @else {
<li class="unfiltered">{{ country.name }}</li>
}
}
</ul>
Mümkün olduğu kadar hızlı hareket etmek istiyorsanız mevcut koddaki kalıpları tek tek aramanız gerekir. Google'ın birkaç bin Angular uygulamasını dahili olarak sürdürmesi ve Angular ekibinin de dahili destek sağlaması burada yardımcı olur. İç kurallardan biri, önemli değişiklikler olması durumunda ilgili güncellemenin yapılmasının gerekli olduğunu öngörmektedir. Elbette, böyle bir birimle bunu manuel olarak yapmak imkansızdır; bu, Angular'ın varsayılan olarak uygulamaların kaynak kodunu yeniden yazan otomatik komut dosyalarını çalıştırdığı anlamına gelir.
Yapısal Direktifler kullanımdan kaldırılmış olarak işaretlenmemiştir ve bu nedenle değişiklik yapılması zorunlu değildir. Ancak geçişi otomatik olarak gerçekleştiren bir komut dosyası vardır. Bunu yapmak için komutu çalıştırmanız yeterlidir
ng g @angular/core:control-flow
Genişletilmiş şablon sözdizimi hâlâ geliştirici önizlemesindedir. Ancak Angular ekibi genel olarak istikrarsızlık veya risk görmüyor. Geliştirici önizleme durumunun ana nedenlerinden biri yeni bir algoritmadır @forbu da renderlamayı hızlandırır.
Ertelenmiş Yükleme/Ertelenebilir Görünümler
Ertelenmiş yükleme, Angular 17.0'ın “ana özelliğidir”. Yeni model olanaklarından yararlanır ve bileşenleri bildirimli olarak ve doğrudan modelde tembel yükleme olarak tanımlamanıza olanak tanır.
Ayrıca bu bileşenin ne zaman bir tarafa yüklenip diğer tarafta etkinleştirilmesi gerektiğine ilişkin kriterleri de sunar.
Çeşitli kriterler kataloğu, örneğin Angular'ın yer tutucu veya bir DOM öğesi görünüm alanında göründüğünde (yani görünür olduğunda) yüklenmeye başlamasını sağlar. Diğer kriterler arasında tıklama, fareyle üzerine gelme, önceden belirlenmiş bir sürenin sona ermesi veya mantığın ayrı ayrı programlanabildiği bir işlev yer alır.
Bileşen ve bağımlılıkları @defer özerk olmalıdır. Konteynerler @defer ancak NgModule olarak bildirilen bir bileşen olabilir.
Aşağıda sizi havaya sokacak basit bir örnek var.
Bir liste içerir Holidays her bir öğe bir kullanıcı arayüzü bileşeni aracılığıyla işlenerek yinelenir. Ancak liste yalnızca kullanıcılar daha önce bir düğmeye tıklayarak Genel Hüküm ve Koşulları (GTC) onaylamışsa görüntülenir.
<h2>Choose among our Holidays</h2>
<button>I hereby agree to the terms</button>
<div class="flex flex-wrap justify-evenly">
@for (holiday of holidays(); track holiday.id) {
<app-holiday-card
[holiday]="holiday"
(addFavourite)="addFavourite($event)"
(removeFavourite)="removeFavourite($event)" />
}
</div>
Bu, yenisinin eklenmesiyle başarılabilir. @defer-Bloklar. Konsol daha sonra derleyicinin içeriğini içeren yeni bir JavaScript dosyası oluşturduğunu hemen gösterir. @defer bağımlılıklar da dahil.
Sayfayı açtığınızda Angular yalnızca düğmeyi gösterir. Koşul ekleme (on interaction(button)) Yükleme işlemini başlatmak için düğmeye tıklamanız yeterlidir.
Ekran görüntüsünde görüldüğü gibi 15 Kbyte hemen silinir. Dosyanın toplam boyutu 35 Kbyte'tır main-Bundle, bu çabaya göre bariz bir artı.
<h2>Choose among our Holidays</h2>
<button mat-raised-button #button>I hereby agree to the terms</button>
<div class="flex flex-wrap justify-evenly">
@defer (on interaction(button)) {
@for (holiday of holidays(); track byId($index, holiday)) {
<app-holiday-card
[holiday]="holiday"
(addFavourite)="addFavourite($event)"
(removeFavourite)="removeFavourite($event)" />
}
}
</div>
JavaScript paketini @defer ile bölün
(Fotoğraf: Rainer Hahnekamp)
Yukarıda da belirttiğimiz gibi birçok kriter bulunmaktadır. Takas yaparak on interaction yaklaşık olarak on viewport Farklı türleri denemek çok kolaydır. Farklı kriterleri birleştirmek de mümkündür.
Ancak pratikte @defer genişleme ile @placeholder kullanım. Böylece kullanıcılara boş bir alan göstermek yerine bir bileşeni veya alternatif metni görüntüleyebilirsiniz.
Yer tutucuya ek olarak yükleme işlemi için ayrı bir blok tanımlama imkanı da bulunmaktadır. Yükleme işlemi, tarayıcının paket dosyasını yüklemesi için geçen süreyi ifade eder.
Yüklenen bileşen arka uca bağlanırsa ve verileri sorgularsa, bileşen zaten etkin olduğundan bu, yükleme işleminin bir parçası değildir.
Bu nedenle daha muhtemel @placeholder bir rol oynuyorlar ve bant genişliği yavaş olan kullanıcılar içeride sıkışıp kalacak @loading Görmem lazım:
<h2>Choose among our Holidays</h2>
@defer (on interaction; on timer(10s)) {
<div class="flex flex-wrap justify-evenly">
@for (holiday of holidays(); track byId($index, holiday)) {
<app-holiday-card
[holiday]="holiday"
(addFavourite)="addFavourite($event)"
(removeFavourite)="removeFavourite($event)"
/>
}
</div>
} @placeholder {
<button mat-raised-button>Show me the holidays.</button>
} @loading {
<p>Loading Holidays...</p>
}
Kullanım durumu artık biraz değişti. Düğme içeride @placeholder taşındı çünkü bu alan zaten her zaman görüntüleniyor. Varsayılan olarak, yer tutucu mevcutsa aynı zamanda ölçüt referansı olarak da kullanılır viewport, interaction vesaire. Bu nedenle model değişkeni (#button) Artık buna gerek yok.
İkinci bir kriter daha var. Yükleme işlemi hala tıklamayı gerektiriyor ancak bu on saniye içinde gerçekleşmezse Angular tatilleri otomatik olarak yeniden yükleyecektir.
Etkisini elde etmek için @loading Bunu görmek için ağ hızını sınırlamak amacıyla tarayıcı araçlarını kullanmaya değer. Aksi takdirde, yer tutucu ile gerçek ekran arasında yalnızca kısa bir “titreşim etkisi” hissedersiniz. Yavaş bir ağda, yükleme boyunca “Tatil Yükleniyor” metnini göreceksiniz.
Ancak daha fazlası da yapılabilir: @loading yükleme süresi için minimum süre sunar. Yalnızca tarayıcı bu sınırı aştığında etkinleştirilir @loading-Engellemek. Titremeyi önlemek için, görüntüleniyorsa yükleme, bu arada Angular bileşeni tamamen yüklemiş olsa bile tanımlanabilir bir süre boyunca görünür kalabilir.
Diğer bir ihtimal de bu prefetch-Seçenek. Bu, Angular'ın paketi erken yüklemeye başlayacağı ancak aktivasyonu bekleyeceği anlamına gelir.
Aşağıdaki örnekte hem önceden getirme hem de parametreleştirilmiş kullanımı görebilirsiniz. @loading:
<h2>Choose among our Holidays</h2>
@defer (on interaction; on timer(10s); prefetch on viewport) {
<div class="flex flex-wrap justify-evenly">
@for (holiday of holidays(); track byId($index, holiday)) {
<app-holiday-card
[holiday]="holiday"
(addFavourite)="addFavourite($event)"
(removeFavourite)="removeFavourite($event)"
/>
}
</div>
} @placeholder {
<button mat-raised-button>Show me the holidays.</button>
} @loading (after 100ms; minimum 1s) {
<p>Loading Holidays...</p>
}
Yer tutucu görünüm alanına girer girmez Angular erken yüklenmeye başlar. Ancak bileşen yalnızca on saniye sonra veya kullanıcılar düğmeyi tıklattığında etkinleşir. Eğer yükleme henüz başlamadıysa en geç o saatte başlayacaktır.
İnternet bağlantısı yavaşsa ve 15 Kbyte'lık indirme işlemi 100 milisaniyeden fazla sürüyorsa kullanıcı en az bir saniye boyunca yükleme ekranını görecektir. Şarj işlemi daha uzun sürerse şarj göstergesi elbette sabit kalacaktır.
Bu örnekte mevcut olan çok sayıda kurala rağmen son kod oldukça okunabilir durumdadır.
@deferred Bu sadece başlangıç. Bildirimsel kod kullanarak önceden karmaşık olan işlevleri çok basit hale getirme yeteneği, bunun potansiyelini gösterir.
Örneğin, tüm Angular projesinin (Framework, CLI, Material) Teknik Lideri Jeremy Elbourn, React'tan bilinenler gibi sunucu bileşenlerini entegre etmenin oldukça mümkün olacağını duyurdu.
Bir yerine @defer Örneğin, bir bloğu şu şekilde tanımlarsınız: @server işaret. Bu daha sonra yalnızca sunucuda görüntülenir ve statik HTML dışında sunucu işlemi tarayıcıya herhangi bir JavaScript göndermez.
Özet ve perspektifler
Sosyal medyadaki “Angular'da bir miktar hareket olduğu” yönündeki mevcut iddia yetersiz bir ifadedir, çünkü Angular şu anda kendini yeniden keşfediyor ve hala geriye dönük olarak uyumlu olmayı başarıyor. Bu makale dizisinde açıklandığı gibi, Angular 17 sürümleri yeni ve kullanışlı özellikler getirdi ancak bunlar aynı zamanda 23 Mayıs 2024'te açıklanan Angular 18 de dahil olmak üzere bu yıl gelecek sürümler için bir hazırlık niteliği taşıyor.
Hidrasyon ve sinyaller temel işlevlerinde zaten mevcuttur ve stabildir. Geliştirme ekibine göre sıvı alımı teknik açıdan en gelişmiş aşamalı sıvı tedavisi olacak. Sinyal girişlerinde de görebileceğiniz gibi, sinyaller giderek daha fazla işlev üstleniyor. Sonuçta performans açısından en üst düzeyde performans gösterecek sinyal bileşenleri başyapıt olacaktır.
(Mayıs)
Haberin Sonu