angular shadow DOM,子组件两次触发 ngOnChanges

问题描述 投票:0回答:1

angular shadow DOM,子组件两次触发ngOnChanges,第一次所有输入数据未定义。如何避免第一次触发?

a.component,就是Shadow DOM。

ts:

import { ChangeDetectorRef, Component, ElementRef, EventEmitter, Input, OnInit, Output, SimpleChanges, ViewChild, ViewEncapsulation } from '@angular/core';

@Component({
  selector: 'app-a',
  templateUrl: './a.component.html',
  styleUrls: ['./a.component.scss'],
  encapsulation: ViewEncapsulation.ShadowDom
})
export class ContainerComponent implements OnInit {
  
  @Input() mode?: string;
  @Input() size?: string;
  @Input() fileList?: any;

  constructor() {}

  ngOnInit(): void {}

}

html:

<div #container>
  <app-b
    [mode]="mode"
    [size]="size"
    [fileList]="fileList">
  </app-b>
</div>

b.组件

ts:

import { ChangeDetectorRef, Component, ElementRef, EventEmitter, Input, OnInit, Output, SimpleChanges, ViewChild, ViewEncapsulation } from '@angular/core';

@Component({
  selector: 'app-b',
  templateUrl: './b.component.html',
  styleUrls: ['./b.component.scss'],
})
export class ContainerComponent implements OnInit {
  
  @Input() mode?: string = 'edit';
  @Input() size?: string = 'm';
  @Input() fileList?: any = [];

  constructor() {}

  ngOnInit(): void {}

  ngOnChanges(changes: SimpleChanges) {
    console.log(changes); 
  }

}


当我导入一个名为 a 的组件,并像下面这样使用它时, ngOnChanges 的功能将在 b 组件中触发两次。第一次得到所有输入数据都是undefined,第二次得到

{size: 'g'}
;此时,
mode
fileList
都变成了
undefined
,而不是默认值
'edit'
[]

<app-a size="g"></app-a>

我想知道如何避免第一次触发?

angular shadow-dom
1个回答
0
投票

首先,ngOnChanges 将在 B(或任何组件)的 onInit 之前触发,第二次将在 B 的 onInit 之后调用,即当绑定数据来自 A 时。您无法避免触发器 - 您只能选择是否“是否会根据更改采取行动。您可以记录更改的事实并不意味着您必须对它们采取行动。

其次,Input 的默认值不是“真正的”默认值,我的意思是不是您期望它表现的那种感觉:如果没有任何内容传递给 Input,即如果value not 绑定在父组件中。但是,您的 A 组件 确实 将值绑定到 B 的输入,这里的问题是 A 本身没有将这些值传递给它。因此,当您仅将 size 传递给 A 时,它会传递给 B,但其他输入将是未定义的,因为它们的值绑定在 A 的模板中,但它们没有值(没有任何值传递给 A)。因此 B 的 onChanges 将在 B 的 onInit 之前触发所有输入的值

undefined
,然后 B 将从 A 获得
size
(因为 A 从其父级获得),因此 B 的
size
将是 'g'。然而,对于其他输入,没有任何东西传递给 A,它们保持未定义状态——所以它们在 B 中也是未定义的,因为它们绑定在 A 的模板中。
如果你想拥有“真正的”默认值,你可以使用 setters 和 getters 作为输入或者在 onInit 中设置值。

© www.soinside.com 2019 - 2024. All rights reserved.