如何为Angular 2组件属性设置默认值?

139

在编写Angular 2.0组件时,如何为属性设置默认值?

例如-我想将foo默认设置为'bar',但绑定可能立即解析为'baz'。这在生命周期钩子中如何实现?

@Component({  
    selector: 'foo-component'
})
export class FooComponent {
    @Input()
    foo: string = 'bar';

    @Input()
    zalgo: string;

    ngOnChanges(changes){
          console.log(this.foo);
          console.log(changes.foo ? changes.foo.previousValue : undefined);
          console.log(changes.foo ? changes.foo.currentValue : undefined);
    }
}

给定以下模板,这是我预期的值。 我错了吗?

<foo-component [foo] = 'baz'></foo-component>

已记录到控制台:

'baz'
'bar'
'baz'
<foo-component [zalgo] = 'released'></foo-component>

已记录到控制台:

'bar'
undefined
undefined

当你尝试它时会发生什么? - JB Nizet
1
@BryanRayner 目前控制台输出的方式是正确的...你遇到了什么问题? - Pankaj Parkar
8
我目前没有遇到问题,只是想澄清预期的行为。当我没有找到答案来满足我的好奇心时,我决定提出这个问题,以防其他人也有同样想要明确的疑问。 - Bryan Rayner
在你的例子中,你忘记了在@Input()上加括号。 - kitimenpolku
对于那些仍在寻找答案的人,Angular官方文档中有一个名为“Input setter coercion”的内容,其中涉及到输入属性的getter和setter。 https://angular.io/guide/template-typecheck#input-setter-coercion - Zvonko
2个回答

186

这是一个有趣的主题。 您可以尝试使用两个生命周期钩子ngOnChangesngOnInit来弄清楚它的工作原理。

基本上,当您将默认值设置为Input时,这意味着该值仅在该组件上没有收到值时才会被使用。 有趣的部分是,在组件初始化之前它将被更改。

假设我们有两个具有两个生命周期钩子和一个从input中传递过来的属性的组件。

@Component({
  selector: 'cmp',
})
export class Login implements OnChanges, OnInit {
  @Input() property: string = 'default';

  ngOnChanges(changes) {
    console.log('Changed', changes.property.currentValue, changes.property.previousValue);
  }

  ngOnInit() {
    console.log('Init', this.property);
  }

}

情况1

在未定义property值的情况下包含在html中的组件

结果将在控制台中显示:Init default

这意味着onChange未被触发。已触发初始化,property值如预期地为default

情况2

在html中设置了属性的组件 <cmp [property]="'new value'"></cmp>

结果将在控制台中显示:

Changed new value Object {}

Init new value

这个很有意思。首先触发了onChange钩子,将property设置为new value,之前的值是空对象!然后才触发带有property新值的onInit钩子。


12
有没有官方文档可以解释这个行为?了解它背后的逻辑和原因会很有帮助,也能够跟踪每个版本中的行为。 - Bryan Rayner
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Mikki Kobvel
1
我正在寻找有关 @Input 具有默认值的文档。@slicepan 提供了组件生命周期文档的链接,但我在文档中没有看到使用默认值的示例。 - nycynik
@nycynik 只需使用以下代码设置默认值:@Input() someProperty = 'someValue'; - magikMaker
1
你是救命恩人。这让我头疼,当我从AngularJS应用程序升级到Angular 7.x时。 - Andris

14

这里是最佳解决方案。(适用于ANGULAR的所有版本)

解决方案:为@Input变量设置默认值。如果没有向该输入变量传递值,则会采用默认值。

我已为此类似问题提供了解决方案。您可以在此处找到完整的解决方案。

export class CarComponent implements OnInit {
  private _defaultCar: car = {
    // default isCar is true
    isCar: true,
    // default wheels  will be 4
    wheels: 4
  };

  @Input() newCar: car = {};

  constructor() {}

  ngOnInit(): void {

   // this will concate both the objects and the object declared later (ie.. ...this.newCar )
   // will overwrite the default value. ONLY AND ONLY IF DEFAULT VALUE IS PRESENT

    this.newCar = { ...this._defaultCar, ...this.newCar };
   //  console.log(this.newCar);
  }
}

这意味着默认的@Input()值{}从未被使用,对吧?你可能可以跳过它: @Input() newCar: car; - Marcel van der Drift
“最好”的定义是相对的。您设置了一个默认值,但当输入发生更改时,您没有再次设置它。 - Mick

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接