Angular @Input 绑定使用函数调用多次

Posted

技术标签:

【中文标题】Angular @Input 绑定使用函数调用多次【英文标题】:Angular @Input binding using function calling multiple times 【发布时间】:2020-04-28 09:38:51 【问题描述】:

我正在使用 Angular 8

我有一个带有 @Input() 属性的子组件。必须在绑定之前修改此输入,因此使用方法返回数据以进行绑定,如

<app-child [info]="getInfo()"></app-child>

而在父组件中,getInfo() 的返回值类似于

getInfo(): any|null 
  console.log('called...');

  if (this.data) 
    return JSON.parse(this.data);
  

  return null;

但是这样一来,每当子组件中发生某些事件时,就会一次又一次地调用该方法。

Stackblitz 示例:https://stackblitz.com/edit/angular-child-com

产生问题:

表单是从接受来自上述方法的输入的子组件呈现的。

单击任何按钮或输入字段,您可以从每个事件的方法调用中看到控制台日志打印字符串。

这会导致子组件中多次OnChange 事件触发。

【问题讨论】:

这是意料之中的。 Angular 不知道 getInfo() 可能返回什么。所以它在每次检测变化时调用它。而且您总是创建并返回一个新对象,因此它每次都绑定该新对象。一劳永逸地解析数据,将结果存储在一个字段中,然后将该字段作为输入传递。 Angular 的默认变更检测策略会在每个变更检测周期中检查所有@Input 绑定的属性。所以在绑定值到@Input属性时避免调用方法 您也可以使用changeDetection: [onPush] 并显式调用更改检测。 【参考方案1】:

您应该检索数据并将其存储在父组件的属性中,然后将其传递给与子组件的数据绑定。 Angular 将负责变更检测

@Component(
  selector: 'app-parent',
  template: '<app-child [info]="info"></app-child>',
)
export class ParentComponent implements OnInit 
  info;

  constructor(private service: SomeDataService) 

  ngOnInit() 
    this.info = this.service.getData();
  

【讨论】:

但是如果你需要一个参数怎么办?因此,您有一个数组需要根据另一个数组的选定值进行过滤,并且这些数组是动态创建的。所以 this.info(arrVal, itemId); 这可以在 setter 或使用 Angular Pipe 中完成。另一个选项是 observable,无论如何我都会推荐它用于 Angular 应用程序中的大多数数据粘合代码。【参考方案2】:

使用async pipes 实现无状态。我认为这更接近你想要做的事情。我尽可能使用异步管道,因为它比对所有内容都使用属性更干净——也减少了意想不到的后果。

@Component(
  selector: 'app-parent',
  template: '<app-child [info]="info$ | async"></app-child>',
)
export class ParentComponent implements OnInit 
  info$ = this.service.getData().pipe(
    map(data => JSON.parse(data))
  );

  constructor(private service: MyService)  

【讨论】:

以上是关于Angular @Input 绑定使用函数调用多次的主要内容,如果未能解决你的问题,请参考以下文章

多次调用Angular Service单例构造函数

Angular @Input getter/setter 和非原始值

Angular 6订阅构造函数上的事件多次调用

在@Input 上使用切片时调用了两次组件的设置器。角度 4

如何在 Angular 2 中调用其构造函数之前将数据发送或绑定到子组件?

Angular - 来自@Input的双向数据绑定不起作用