Angular child 当 parent 在 parent oninit 期间运行时组件未初始化
Angular child component not initialised when parent is function during parent oninit
我在 ResetPasswordComponent
oninit 中触发时显示警报时遇到问题。 AlertService
的订阅块没有被触发,但是如果我将代码从 oninit 移动到构造函数,它将起作用。但是,将 initialization/declaration 代码放入构造函数似乎不是一个好习惯。那么有没有更好的解决办法呢?
Parent
export class ResetPasswordComponent implements OnInit {
public email: string;
public token: string;
constructor(public alertService: AlertService) {
}
ngOnInit() {
this.token = this.route.snapshot.queryParamMap.get('token');
this.email = this.route.snapshot.queryParamMap.get('email');
console.log("Parent on init");
if (this.token === null || this.token === "" ||
this.email === null || this.email === "") {
this.form.disable();
this.alertService.error("Invalid link");
}
}
}
Child
export class AlertComponent implements OnInit, OnDestroy {
private subscription: Subscription;
public messages: string[];
public type: string;
constructor(private alertService: AlertService) {
}
ngOnInit() {
console.log(this.alertService.getAlert());
this.subscription = this.alertService.getAlert().subscribe(data => {
console.log("OK");
// do something
});
console.log("Child On init");
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}
警报服务
@Injectable({ providedIn: 'root' })
export class AlertService {
private subject = new Subject<Alert>();
constructor(private router: Router) { }
error(message: any, navigateTo = null) {
if (navigateTo !== null) {
this.navigateWithMessage(navigateTo, AlertType.error, message);
}
const alert: Alert = { type: AlertType.error, message };
this.subject.next(alert);
console.log("NEXT");
}
getAlert(): Observable<Alert> {
return this.subject.asObservable();
}
我认为问题在于事件是在子组件开始在 ngOnInit 中订阅之前触发的。当子组件最终订阅时,"Invalid link" 事件已经发生并结束。
有几个解决方案,一个是将您的主题更改为 BehaviorSubject,例如:
private subject = new BehaviorSubject<Alert>(null);
现在,一旦子订阅,它就会收到来自 Observable 的最后一个事件,即使事件已经发生。
另一种解决方案是将 shareReplay() 运算符添加到您的可观察对象中。但在这种特定情况下,当您已经在使用主题时,我会选择 BehaviorSubject 解决方案。
我在 ResetPasswordComponent
oninit 中触发时显示警报时遇到问题。 AlertService
的订阅块没有被触发,但是如果我将代码从 oninit 移动到构造函数,它将起作用。但是,将 initialization/declaration 代码放入构造函数似乎不是一个好习惯。那么有没有更好的解决办法呢?
Parent
export class ResetPasswordComponent implements OnInit {
public email: string;
public token: string;
constructor(public alertService: AlertService) {
}
ngOnInit() {
this.token = this.route.snapshot.queryParamMap.get('token');
this.email = this.route.snapshot.queryParamMap.get('email');
console.log("Parent on init");
if (this.token === null || this.token === "" ||
this.email === null || this.email === "") {
this.form.disable();
this.alertService.error("Invalid link");
}
}
}
Child
export class AlertComponent implements OnInit, OnDestroy {
private subscription: Subscription;
public messages: string[];
public type: string;
constructor(private alertService: AlertService) {
}
ngOnInit() {
console.log(this.alertService.getAlert());
this.subscription = this.alertService.getAlert().subscribe(data => {
console.log("OK");
// do something
});
console.log("Child On init");
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}
警报服务
@Injectable({ providedIn: 'root' })
export class AlertService {
private subject = new Subject<Alert>();
constructor(private router: Router) { }
error(message: any, navigateTo = null) {
if (navigateTo !== null) {
this.navigateWithMessage(navigateTo, AlertType.error, message);
}
const alert: Alert = { type: AlertType.error, message };
this.subject.next(alert);
console.log("NEXT");
}
getAlert(): Observable<Alert> {
return this.subject.asObservable();
}
我认为问题在于事件是在子组件开始在 ngOnInit 中订阅之前触发的。当子组件最终订阅时,"Invalid link" 事件已经发生并结束。
有几个解决方案,一个是将您的主题更改为 BehaviorSubject,例如:
private subject = new BehaviorSubject<Alert>(null);
现在,一旦子订阅,它就会收到来自 Observable 的最后一个事件,即使事件已经发生。
另一种解决方案是将 shareReplay() 运算符添加到您的可观察对象中。但在这种特定情况下,当您已经在使用主题时,我会选择 BehaviorSubject 解决方案。