我最近将 Angular 应用程序更新到版本 17,并遇到了名为“信号”的新功能。我已经阅读了有关对可能经常更改、在应用程序的多个部分中使用或暴露于外界的变量使用信号的一般准则。
我正在开发一个具有各种组件变量的
SignInComponent
,并且我正在尝试确定哪些变量应该被标记为信号,以便有效地从这个新功能中受益。这是我的 SignInComponent
的简化版本:
import { Subscription } from 'rxjs';
import { Router } from '@angular/router';
import { appSettings } from '@app/configs';
import { ToastrService } from 'ngx-toastr';
import { ISignInForm } from '../../models';
import { ISignInPayload } from '@shared/models';
import { NgProgress, NgProgressRef } from 'ngx-progressbar';
import { AuthenticationService } from '@core/authentication';
import { Component, OnInit, OnDestroy } from '@angular/core';
import {
FormGroup,
FormBuilder,
FormControl,
AbstractControl
} from '@angular/forms';
@Component({
selector: 'sign-in',
templateUrl: './sign-in.component.html',
styleUrls: ['./sign-in.component.css']
})
export class SignInComponent implements OnInit, OnDestroy {
constructor(
private _router: Router,
private _progress: NgProgress,
private _toastr: ToastrService,
private _formBuilder: FormBuilder,
private _authService: AuthenticationService
) {
this.initSignInForm();
this.setCredentailsOnRememberMe();
}
public submitted = false;
public isDisabled = false;
private progressRef!: NgProgressRef;
private subscriptions: Subscription[] = [];
public signInForm!: FormGroup<ISignInForm>;
private rememberMeKey: string = appSettings.rememberMeKey;
ngOnInit(): void {
this.progressRef = this._progress.ref('progress-bar');
}
private initSignInForm(): void {
this.signInForm = this._formBuilder.group<ISignInForm>({
email: new FormControl('', {
nonNullable: true,
validators: [Validators.email, Validators.required]
}),
password: new FormControl('', {
nonNullable: true,
validators: [Validators.required]
}),
rememberMe: new FormControl(false, {
nonNullable: true
})
});
}
public get formControl(): {
[key: string]: AbstractControl;
} {
return this.signInForm.controls;
}
public signInOnSubmit(): void {
this.submitted = true;
if (this.isDisabled || this.signInForm.invalid) return;
this.isDisabled = true;
this.progressRef.start();
const formValue = this.signInForm.getRawValue();
const payload: ISignInPayload = {
email: formValue.email,
password: formValue.password
};
this.subscriptions.push(
this._authService.signIn(payload).subscribe({
next: (signInResult) => {
//Reset flags and complete loading spinner
this.submitted = false;
this.isDisabled = false;
this.progressRef.complete();
//Store form values in localStorage if "Remember Me" is checked
if (formValue.rememberMe) {
localStorage.setItem(
this.rememberMeKey,
JSON.stringify(formValue)
);
} else {
localStorage.removeItem(this.rememberMeKey);
}
},
error: (signInError) => {
this.submitted = false;
this.isDisabled = false;
this.progressRef.complete();
this._toastr.error(signInError.message);
}
})
);
}
private setCredentailsOnRememberMe() {
let rememberMeData!: {
email: string;
password: string;
rememberMe: boolean;
};
const storedData = localStorage.getItem(this.rememberMeKey);
if (!!storedData) {
rememberMeData = JSON.parse(storedData);
}
if (!!rememberMeData && rememberMeData.rememberMe) {
this.signInForm.patchValue({
email: rememberMeData.email,
password: rememberMeData.password,
rememberMe: rememberMeData.rememberMe
});
}
}
ngOnDestroy(): void {
this.subscriptions.forEach((subscription) => subscription.unsubscribe());
}
}
在 Angular 中你不能直接将变量标记为信号;相反,您可以将它们转换为信号。
角度信号是带有方法的函数,而不仅仅是变量。信号反应性主要影响模板。
有关此主题的更多信息,您可能会发现以下文章很有帮助:创建角度组件:模板优先声明式方法(本文不是在付费专区后面)