angular shadow DOM,子组件两次触发ngOnChanges,第一次所有输入数据未定义。如何避免第一次触发?
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>
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>
我想知道如何避免第一次触发?
首先,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 中设置值。