@ Input()值总是未定义

我已经创建了一个 user photo component,它接受一个 @Input()值,这个值是 userId。如果该值被传入,那么我将从 Firebase中检索链接到这个 userId 的信息,如果没有,那么我将执行其他操作。

我的用户照片组件

import { Component, OnInit, OnDestroy, Input } from '@angular/core';


@Component({
selector: 'user-photos',
templateUrl: './user-photos.component.html',
styleUrls: ['./user-photos.component.css']
})


export class UserPhotoComponent implements OnInit {


@Input() userId: string;


constructor() {


console.log('userId is:',this.userId);


}




ngOnInit() {




}


ngOnDestroy() {


}
}

正如您所看到的,我已经将 userId 声明为 @Input(),现在在我的 edit-profile component上有以下内容:

<user-photos [userId]="TestingInput"></user-photos>

现在,当我看到 h1标签出现时,用户照片组件得到呈现,但是 userId 总是未定义?

在开发人员控制台中没有出现错误,所以我不能完全确定我做错了什么。

97052 次浏览

它将在 ngOnInit中初始化,而不是构造函数

ngOnInit() {
console.log('userId is:',this.userId);
}

此外,如果你想传递一个像字符串一样的文字,并使用括号 [],你必须通过用单个的滴答声包围它作为一个字符串传递。

<user-photos [userId]="'TestingInput'"></user-photos>

原因是包含的表达式是在包含组件的上下文中计算的,所以如果没有它,它将尝试检索和传递一个名为 TestingInput的属性/字段,这个属性/字段将是未定义的(除非你碰巧也有一个字段叫这个名字)。

在我的例子中,我将 undefined作为 输入传入,并假设 Angular 将把未定义的情况作为默认情况处理。这个假设是错误的,即使它没有清楚地概述在 角度的组件交互文档。下面是用例场景:

Html:

...
[mVal]="undefined"
...

子组件:

...
@input('mVal')
mVal: boolean = true
...

mVal的值将是 undefined,而不是您可能预期的 true

只有当它在父组件上是 没有定义时,Angular 才会使该值为 true (默认情况下) ; 否则为 它将按原样传入值(即使它是 undefined)。

您可以通过检查该值是否在 OnInit或甚至在组件的构造函数中未定义来解决这个问题。

在我的例子中,我必须首先在父模板上使用 * ngIf = “ isLoaded”。

关于父组件

    <div *ngIf = "isLoaded">
<app-child-component [dataToChild]="dataFromParent"> </app-child-component>
</div>

关于子组件

      @Input() dataToChild: any;
constructor() { }
ngOnInit(): void {
console.log(this.dataToChild);
}

回答你的问题

@ Input ()值总是未定义

NgOnInit 中没有定义的原因是,在组件初始化的时候,实际上没有传入 userId。

<user-photos [userId]="TestingInput"></user-photos>

为了在 OnInit ()函数中获取@Input 值,您可以执行以下操作:

我的用户照片组件

import { Component, OnInit, OnDestroy, Input } from '@angular/core';


@Component({
selector: 'user-photos',
templateUrl: './user-photos.component.html',
styleUrls: ['./user-photos.component.css']
})


export class UserPhotoComponent implements OnInit {


@Input() userId: string;


constructor() {  }


ngOnInit() {
setTimeout(() => {
console.log('userId is:',this.userId);  // You will get the @Input value
});
}


ngOnDestroy() {


}
}

如果您的输入延迟了(例如,一个缓慢的 webservice) ,那么在响应从 webservice 到达之前,该值首先是未定义的。

为了调试它,您可以使用 ngOnChanges () hook,它将每次触发一个输入值变化:

ngOnChanges() {
console.log('data', this.data);
}

它会输出类似于:

data undefined <-OnInit,值尚未到达

data here it is! <-value 到达延迟

这些答案中的任何一个对我都不起作用,经过一些研究我发现了爱的解决方案,

以超文本标示语言(HTML)。

<app-opportunityTable [tableNAme]="'OPPORTUNITY'"></app-opportunityTable>

子组件

@Component( {
selector: 'app-opportunityTable',
templateUrl: './opportunityTable.component.html',
styleUrls: ['./opportunityTable.component.css'],
inputs: ['tableNAme']
} )


export class opportunityTable implements OnInit {
ngOnInit() {
console.log( "this is it" + this.tableNAme )
}
}

如果希望使用硬编码字符串作为参数,请使用单个刻度

<app-mycomponent [inputProperty]="'test'"></app-mycomponent>

如果 TestingInput 是 变量,而 不值钱最好加上 *ngIf="TestingInput"

<user-photos [userId]="TestingInput" *ngIf="TestingInput "></user-photos>

如果我们调用某个 api,响应的延迟可能会导致传递一个空值

它也可以是未定义的,如果你有多个输入,在我的版本的角度是这种情况:

export class Foo {
@Input() bar: string; // fine
@Input() baz: string; // does not exist (console.log(this) does not show it)
}

你是否也把它传递进去并不重要。看起来早期版本的 Angular 不允许这样做。如果需要多个输入,请传递一个具有多个字段的对象。

我花了很多时间在这个愚蠢的“输入”错误上,它应该是:

<user-photos
[userId]="TestingInput">
</user-photos>

而不是

<user-photos>
[userId]="TestingInput"
</user-photos>

如果有人像我一样犯了语法错误,也许会有帮助