为什么@Input属性在ngOnInit中没有定义?



在这个组件中,我使用一个服务从API获取一些数据

@Component({
selector: 'app-question-presenter',
template: `
<div class="question-presenter">
<app-question [question]="question"></app-question>
</div>
`
})
export class QuestionPresenterComponent implements OnInit {
private requestId: string;
private userId: string;
private question: Question;
constructor(
private route: ActivatedRoute,
private router: Router,
private questionService: QuestionService
) { }
ngOnInit() {
this.route.params.pipe(
switchMap((params: Params) => {
return this.questionService.getQuestion(params.requestId);
})
).subscribe((data: any) => this.question = data.data[0].question);
}
}

在另一个组件(提供app-question的组件(中,我正在尝试访问question但在控制台中undefined

@Component({
selector: 'app-question',
templateUrl: './question.component.html',
styleUrls: ['./question.component.scss']
})
export class QuestionComponent implements OnInit {
@Input()
question: Question;
constructor() {}
ngOnInit() {
console.log(this.question);
}

我知道数据正在进入模板(因为它按预期呈现(,但我认为Input会在调用ngOnInit之前加载 - 我做错了什么?

您可以延迟组件的创建,直到值准备就绪。

<app-question *ngIf="question" [question]="question"></app-question>

您还可以使用可观察量

this.question$ = this.route.params.pipe(
switchMap(({requestId) => this.questionService.getQuestion(requestId))
)

然后在模板中:

<app-question *ngIf="question$ | async as question" [question]="question"></app-question>

看起来您正在进行竞争条件。如果担心它仅显示在模板上,可以将异步管道添加到要绑定到的属性。仅当属性具有值时,它才会显示。这将订阅问题属性并相应地取消订阅。

.html

<div>
<p>{{question | async }}</p>
</div>

如果您希望在组件本身中使用变量,我会订阅您的 QuestionPresenterComponent 中的 question 属性。

为了使它更加干净,我建议将该变量与您的API调用一起放在共享服务中,这样所有订阅者都将相应地继承更新。

@Component({
selector: 'app-question',
templateUrl: './question.component.html',
styleUrls: ['./question.component.scss']
})
export class QuestionComponent implements OnInit {
@Input()
question: Question;
constructor(private sharedService: SharedService) {}
ngOnInit() {
this.sharedService.question.subscribe(question => {
console.log(question)
});
}

最新更新