Tüm Avantajlar, Sorunsuz: Angular 9 Eğitimi
Yayınlanan: 2022-03-11"İnternet her yıl bozulur" der ve geliştiricilerin genellikle gidip düzeltmeleri gerekir. Uzun zamandır beklenen Angular sürüm 9 ile bunun geçerli olacağı ve önceki sürümlerde geliştirilen uygulamaların büyük bir geçiş sürecinden geçmesi gerektiği düşünülebilir.
Ama durum böyle değil! Angular ekibi, derleyicisini tamamen yeniden tasarlayarak daha hızlı derlemeler, daha hızlı test çalıştırmaları, daha küçük paket boyutları ve en önemlisi eski sürümlerle geriye dönük uyumluluk sağladı. Angular 9 ile geliştiriciler temel olarak tüm avantajları herhangi bir güçlük çekmeden elde eder.
Bu Angular 9 eğitiminde, sıfırdan bir Angular uygulaması oluşturacağız. En yeni Angular 9 özelliklerinden bazılarını kullanacağız ve yol boyunca diğer iyileştirmeleri gözden geçireceğiz.
Angular 9 Eğitimi: Yeni Bir Angular Uygulamasıyla Başlamak
Angular proje örneğimize başlayalım. İlk olarak, Angular'ın CLI'sinin en son sürümünü yükleyelim:
npm install -g @angular/cli
Angular CLI versiyonunu ng version
çalıştırarak doğrulayabiliriz.
Ardından, bir Angular uygulaması oluşturalım:
ng new ng9-app --create-application=false --strict
ng new
komutumuzda iki argüman kullanıyoruz:
-
--create-application=false
, CLI'ye yalnızca çalışma alanı dosyaları oluşturmasını söyler. Bu, birden fazla uygulamaya ve birden fazla kitaplığa ihtiyacımız olduğunda kodumuzu daha iyi düzenlememize yardımcı olacaktır. -
--strict
, daha fazla TypeScript yazmayı ve kod temizliğini zorlamak için daha katı kurallar ekler.
Bunun sonucunda elimizde temel bir workspace klasör ve dosyalarımız oluyor.
Şimdi yeni bir uygulama ekleyelim. Bunu yapmak için çalıştıracağız:
ng generate application tv-show-rating
Sorulacak:
? Would you like to share anonymous usage data about this project with the Angular Team at Google under Google's Privacy Policy at https://policies.google.com/privacy? For more details and how to change this setting, see http://angular.io/analytics. No ? Would you like to add Angular routing? Yes ? Which stylesheet format would you like to use? SCSS
Şimdi, ng serve
'yi çalıştırırsak, uygulamanın ilk iskelesi ile çalıştığını göreceğiz.
ng build --prod
çalıştırırsak, oluşturulan dosyaların listesini görebiliriz.
Her dosyanın iki versiyonu var. Biri eski tarayıcılarla uyumludur ve diğeri, daha yeni API'ler kullanan ve tarayıcılarda çalıştırmak için daha az çoklu dolgu gerektiren ES2015'i hedefleyen derlenmiştir.
Angular 9'daki büyük gelişmelerden biri paket boyutudur. Angular ekibine göre büyük uygulamalarda %40'a varan düşüşler görebilirsiniz.
Yeni oluşturulan bir uygulama için paket boyutu, Angular 8'inkine oldukça benzer, ancak uygulamanız büyüdükçe, paket boyutunun önceki sürümlere göre küçüldüğünü göreceksiniz.
Angular 9'da tanıtılan bir diğer özellik, bileşen stili CSS dosyalarından herhangi biri tanımlanmış bir eşikten büyükse bizi uyarma yeteneğidir.
Bu, kötü stil içe aktarmalarını veya çok büyük bileşen stili dosyalarını yakalamamıza yardımcı olacaktır.
TV Şovlarını Derecelendirmek için Form Ekleme
Ardından, TV şovlarını derecelendirmek için bir form ekleyeceğiz. Bunun için önce bootstrap
ve ng-bootstrap
yükleyeceğiz:
npm install bootstrap @ng-bootstrap/ng-bootstrap
Angular 9'daki bir başka gelişme de i18n'dir (uluslararasılaştırma). Önceden, geliştiricilerin bir uygulamadaki her yerel ayar için tam bir derleme çalıştırması gerekirdi. Bunun yerine Angular 9, bir uygulamayı bir kez oluşturmamıza ve tüm i18n dosyalarını derleme sonrası bir süreçte oluşturmamıza olanak tanıyarak derleme süresini önemli ölçüde azaltır. ng-bootstrap
i18n'ye bağımlı olduğundan, yeni paketi projemize ekleyeceğiz:
ng add @angular/localize
Ardından, Bootstrap temasını uygulamamızın styles.scss
:
@import "~bootstrap/scss/bootstrap";
NgbModule
ve ReactiveFormsModule
AppModule
app.module.ts
:
// ... import { ReactiveFormsModule } from '@angular/forms'; import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; @NgModule({ imports: [ // ... ReactiveFormsModule, NgbModule ], })
Ardından, app.component.html
formumuz için temel bir ızgarayla güncelleyeceğiz:
<div class="container"> <div class="row"> <div class="col-6"> </div> </div> </div>
Ve form bileşenini oluşturun:
ng gc TvRatingForm
tv-rating-form.component.html
güncelleyelim ve TV şovlarını derecelendirmek için formu ekleyelim.
<form [formGroup]="form" (ngSubmit)="submit()" class="mt-3"> <div class="form-group"> <label>TV SHOW</label> <select class="custom-select" formControlName="tvShow"> <option *ngFor="let tvShow of tvShows" [value]="tvShow.name">{{tvShow.name}}</option> </select> </div> <div class="form-group"> <ngb-rating [max]="5" formControlName="rating"></ngb-rating> </div> <button [disabled]="form.invalid || form.disabled" class="btn btn-primary">OK</button> </form>
Ve tv-rating-form.component.ts
görünecektir:
// ... export class TvRatingFormComponent implements OnInit { tvShows = [ { name: 'Better call Saul!' }, { name: 'Breaking Bad' }, { name: 'Lost' }, { name: 'Mad men' } ]; form = new FormGroup({ tvShow: new FormControl('', Validators.required), rating: new FormControl('', Validators.required), }); submit() { alert(JSON.stringify(this.form.value)); this.form.reset(); } }
Son olarak, formu app.component.html
:
<!-- ... --> <div class="col-6"> <app-tv-rating-form></app-tv-rating-form> </div>
Bu noktada, bazı temel UI işlevlerine sahibiz. Şimdi, tekrar servisi çalıştırırsak, ng serve
görebiliriz.
Devam etmeden önce, hata ayıklamaya yardımcı olmak için eklenen bazı ilginç yeni Angular 9 özelliklerine hızlıca göz atalım. Bu günlük işimizde çok yaygın bir görev olduğundan, hayatımızı biraz daha kolaylaştırmak için neyin değiştiğini bilmeye değer.
Angular 9 Ivy ile hata ayıklama
Angular 9 ve Angular Ivy'de sunulan bir diğer büyük gelişme de hata ayıklama deneyimidir. Derleyici artık daha fazla hata algılayabilir ve bunları daha "okunabilir" bir şekilde atabilir.
Eylemde görelim. İlk olarak, tsconfig.json
şablon kontrolünü etkinleştireceğiz:
{ // ... "angularCompilerOptions": { "fullTemplateTypeCheck": true, "strictInjectionParameters": true, "strictTemplates": true } }
Şimdi, tvShows
dizisini güncellersek ve name
title
olarak değiştirirsek:
tvShows = [ { title: 'Better call Saul!' }, { title: 'Breaking Bad' }, { title: 'Lost' }, { title: 'Mad men' } ];
…derleyiciden bir hata alacağız.
Bu tür denetimi, yazım hatalarını ve TypeScript türlerinin yanlış kullanımını önlememizi sağlar.
@Input()
için Angular Ivy Doğrulaması
Aldığımız bir başka iyi doğrulama da @Input()
ile. Örneğin, bunu tv-rating-form.component.ts
:
@Input() title: string;
…ve onu app.component.html
:
<app-tv-rating-form [title]="title"></app-tv-rating-form>
…ve ardından app.component.ts
şu şekilde değiştirin:
// ... export class AppComponent { title = null; }
Bu üç değişikliği yaparsak, derleyiciden başka bir tür hata alırız.
Bunu atlamak istersek, değeri any
çevirmek ve hatayı düzeltmek için şablonda $any()
kullanabiliriz :
<app-tv-rating-form [title]="$any(title)"></app-tv-rating-form>
Bununla birlikte, bunu düzeltmenin doğru yolu, formdaki title
geçersiz kılmak olacaktır:
@Input() title: string | null ;
Angular 9 ExpressionChangedAfterItHasBeenCheckedError
İfadeChangedAfterItHasBeenCheckedError
Angular geliştirmedeki en korkunç hatalardan biri ExpressionChangedAfterItHasBeenCheckedError
. Neyse ki, Ivy hatayı daha net bir şekilde verir ve sorunun nereden geldiğini bulmayı kolaylaştırır.
Öyleyse, bir ExpressionChangedAfterItHasBeenCheckedError
hatası verelim. Bunu yapmak için önce bir hizmet üreteceğiz:
ng gs Title
Ardından, bir BehaviorSubject
ve Observable
erişmek ve yeni bir değer yaymak için yöntemler ekleyeceğiz.
export class TitleService { private bs = new BehaviorSubject < string > (''); constructor() {} get title$() { return this.bs.asObservable(); } update(title: string) { this.bs.next(title); } }
Bundan sonra, bunu app.component.html
:

<!-- ... --> <div class="col-6"> <h2> {{title$ | async}} </h2> <app-tv-rating-form [title]="title"></app-tv-rating-form> </div>
Ve app.component.ts
içinde TitleService
öğesini enjekte edeceğiz:
export class AppComponent implements OnInit { // ... title$: Observable < string > ; constructor( private titleSvc: TitleService ) {} ngOnInit() { this.title$ = this.titleSvc.title$; } // ... }
Son olarak, tv-rating-form.component.ts
içinde TitleService
enjekte edeceğiz ve bir ExpressionChangedAfterItHasBeenCheckedError
hatası verecek olan AppComponent
başlığını güncelleyeceğiz.
// ... constructor( private titleSvc: TitleService ) { } ngOnInit() { this.titleSvc.update('new title!'); }
Artık ayrıntılı hatayı tarayıcının geliştirme konsolunda görebiliriz ve app.component.html
tıklamak bizi hatanın nerede olduğunu gösterir.
Servis çağrısını setTimeout
ile sararak bu hatayı düzeltebiliriz:
setTimeout(() => { this.titleSvc.update('new title!'); });
ExpressionChangedAfterItHasBeenCheckedError
hatasının neden oluştuğunu anlamak ve diğer olasılıkları keşfetmek için Maxim Koretskyi'nin konuyla ilgili yazısı okunmaya değer.
Angular Ivy, hataların daha net bir şekilde sunulmasını sağlar ve kodumuzda TypeScript yazarak zorlamaya yardımcı olur. Aşağıdaki bölümde, Ivy ve hata ayıklamadan yararlanacağımız bazı yaygın senaryoları ele alacağız.
Bileşen Donanımlarıyla Angular 9 Uygulamamız için Test Yazma
Angular 9'da bileşen koşumları adı verilen yeni bir test API'si tanıtıldı. Bunun arkasındaki fikir, DOM ile etkileşim için gereken tüm işleri ortadan kaldırarak çalışmayı çok daha kolay ve çalıştırmayı daha kararlı hale getirmektir.
Bileşen koşum API'si @angular/cdk
kitaplığına dahil edilmiştir, bu yüzden önce bunu projemize yükleyelim:
npm install @angular/cdk
Artık bir test yazabilir ve bileşen koşumlarından yararlanabiliriz. tv-rating-form.component.spec.ts
içinde testi ayarlayalım:
import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; import { ReactiveFormsModule } from '@angular/forms'; describe('TvRatingFormComponent', () => { let component: TvRatingFormComponent; let fixture: ComponentFixture < TvRatingFormComponent > ; beforeEach(async (() => { TestBed.configureTestingModule({ imports: [ NgbModule, ReactiveFormsModule ], declarations: [TvRatingFormComponent] }).compileComponents(); })); // ... });
Ardından, bileşenimiz için bir ComponentHarness
uygulayalım. İki koşum takımı oluşturacağız: biri TvRatingForm
için, diğeri NgbRating
için. ComponentHarness
, bileşenin seçicisinin değerini alması gereken hostSelector
adlı static
bir alan gerektirir.
// ... import { ComponentHarness, HarnessLoader } from '@angular/cdk/testing'; import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; class TvRatingFormHarness extends ComponentHarness { static hostSelector = 'app-tv-rating-form'; } class NgbRatingHarness extends ComponentHarness { static hostSelector = 'ngb-rating'; } // ...
TvRatingFormHarness
için, gönder düğmesi için bir seçici ve bir click
tetikleyecek bir işlev oluşturacağız. Bunu uygulamanın ne kadar kolaylaştığını görebilirsiniz.
class TvRatingFormHarness extends ComponentHarness { // ... protected getButton = this.locatorFor('button'); async submit() { const button = await this.getButton(); await button.click(); } }
Ardından, bir derecelendirme belirlemek için yöntemler ekleyeceğiz. Burada, kullanıcının tıklayabileceği yıldızları temsil eden tüm <span>
öğelerini aramak için locatorForAll
kullanıyoruz. rate
işlevi, yalnızca olası tüm derecelendirmelerin yıldızlarını alır ve gönderilen değere karşılık gelene tıklar.
class NgbRatingHarness extends ComponentHarness { // ... protected getRatings = this.locatorForAll('span:not(.sr-only)'); async rate(value: number) { const ratings = await this.getRatings(); return ratings[value - 1].click(); } }
Eksik olan son parça, NgbRatingHarness
TvRatingFormHarness
. Bunu yapmak için, TvRatingFormHarness
sınıfına konumlandırıcıyı eklememiz yeterlidir.
class TvRatingFormHarness extends ComponentHarness { // ... getRating = this.locatorFor(NgbRatingHarness); // ... }
Şimdi testimizi yazalım:
describe('TvRatingFormComponent', () => { // ... it('should pop an alert on submit', async () => { spyOn(window, 'alert'); const select = fixture.debugElement.query(By.css('select')).nativeElement; select.value = 'Lost'; select.dispatchEvent(new Event('change')); fixture.detectChanges(); const harness = await TestbedHarnessEnvironment.harnessForFixture(fixture, TvRatingFormHarness); const rating = await harness.getRating(); await rating.rate(1); await harness.submit(); expect(window.alert).toHaveBeenCalledWith('{"tvShow":"Lost","rating":1}'); }); });
Form içindeki seçimimiz select
değerini bir koşum takımı aracılığıyla ayarlamadığımıza dikkat edin. Bunun nedeni, API'nin hala bir seçenek belirlemeyi desteklememesidir. Ancak bu bize burada, bileşenlerle etkileşimin bileşen kablo demetlerinden önce nasıl göründüğünü karşılaştırma şansı veriyor.
Testleri çalıştırmadan önce son bir şey. title
null
olarak güncellediğimiz için app.component.spec.ts
düzeltmemiz gerekiyor.
describe('AppComponent', () => { // ... it(`should have as title 'tv-show-rating'`, () => { const fixture = TestBed.createComponent(AppComponent); const app = fixture.componentInstance; expect(app.title).toEqual(null); }); });
Şimdi ng test
çalıştırdığımızda testimiz geçiyor.
Angular 9 Örnek Uygulamamıza Geri Dönün: Verileri Veritabanına Kaydetme
Firestore'a bir bağlantı ekleyerek ve derecelendirmeleri veritabanına kaydederek Angular 9 eğitimimizi tamamlayalım.
Bunu yapmak için bir Firebase Projesi oluşturmamız gerekiyor. Ardından, gerekli bağımlılıkları yükleyeceğiz.
npm install @angular/fire firebase
Firebase Konsolu'nun proje ayarlarında, yapılandırmasını alacağız ve bunları environment.ts
ve environment.prod.ts
ekleyeceğiz:
export const environment = { // ... firebase: { apiKey: '{your-api-key}', authDomain: '{your-project-id}.firebaseapp.com', databaseURL: 'https://{your-project-id}.firebaseio.com', projectId: '{your-project-id}', storageBucket: '{your-project-id}.appspot.com', messagingSenderId: '{your-messaging-id}', appId: '{your-app-id}' } };
Bundan sonra, app.module.ts
içindeki gerekli modülleri içe aktaracağız:
import { AngularFireModule } from '@angular/fire'; import { AngularFirestoreModule } from '@angular/fire/firestore'; import { environment } from '../environments/environment'; @NgModule({ // ... imports: [ // ... AngularFireModule.initializeApp(environment.firebase), AngularFirestoreModule, ], // ... })
Ardından, tv-rating-form.component.ts
AngularFirestore
hizmetini enjekte edeceğiz ve form gönderiminde yeni bir derecelendirme kaydedeceğiz:
import { AngularFirestore } from '@angular/fire/firestore'; export class TvRatingFormComponent implements OnInit { constructor( // ... private af: AngularFirestore, ) { } async submit(event: any) { this.form.disable(); await this.af.collection('ratings').add(this.form.value); this.form.enable(); this.form.reset(); } }
Şimdi Firebase Konsoluna gittiğimizde yeni oluşturulan itemi göreceğiz.
Son olarak, tüm derecelendirmeleri AppComponent
. Bunu yapmak için app.component.ts
içinde, koleksiyondaki verileri alacağız:
import { AngularFirestore } from '@angular/fire/firestore'; export class AppComponent implements OnInit { // ... ratings$: Observable<any>; constructor( // ... private af: AngularFirestore ) { } ngOnInit() { // ... this.ratings$ = this.af.collection('ratings').valueChanges(); } }
…ve app.component.html
bir derecelendirme listesi ekleyeceğiz:
<div class="container"> <div class="row"> // ... <div class="col-6"> <div> <p *ngFor="let rating of ratings$ | async"> {{rating.tvShow}} ({{rating.rating}}) </p> </div> </div> </div> </div>
Angular 9 eğitim uygulamamız bir araya getirildiğinde böyle görünüyor.
Angular 9 ve Angular Ivy: Daha İyi Geliştirme, Daha İyi Uygulamalar ve Daha İyi Uyumluluk
Bu Angular 9 eğitiminde, temel bir form oluşturmayı, verileri Firebase'e kaydetmeyi ve ondan öğeleri almayı ele aldık.
Yol boyunca, Angular 9 ve Angular Ivy'de hangi iyileştirmelerin ve yeni özelliklerin yer aldığını gördük. Tam bir liste için resmi Angular blogunun en son yayın gönderisine göz atabilirsiniz.
Bir Google Cloud İş Ortağı olarak, Toptal'ın Google sertifikalı uzmanları, en önemli projeleri için şirketlere talep üzerine hizmet vermektedir.