@Input是否提供双向绑定?

时间:2018-11-08 14:09:47

标签: angular input

我认为@Input的工作方式会直接给出一个很大的“否!”这个问题。但是,今天我偶然发现了一些奇怪的行为,或者也许我一直以为@Input错误的方式。

我做了一个stackblitz来说明问题。这发生在Angular 7.0.1的stackblitz中,但是在我的本地项目中,它也发生在Angular 6.1.2中。

stackblitz显示了一个具有对象的简单父组件。该对象通过@Input传递给子组件。子组件和父组件均具有更改对象的功能。它们也都在模板中显示对象的值。

我希望看到当父对象更改对象时,它将在子对象中更改对象。但是,我没想到当孩子更改对象时,它也会为父对象更改它。堆栈闪电确实显示了此行为。我一直以为您将需要通过@Output显式发出一个事件,以建立到父级的流程并在子级组件中进行更改。

4 个答案:

答案 0 :(得分:4)

答案是“否”。在您的示例中,传递给@Input属性的值是对对象的引用。如果您有双向绑定,则可以在子组件中为该属性分配一个新对象:

this.thing = { name: "world", nbm: 10 };

和父组件中的相应属性将相应更新。如您在this stackblitz中所见,情况并非如此。

但是,由于父组件和子组件都引用了同一对象,因此它们都可以修改其对象之一的属性,而该更改将在另一组件中观察到。


为了实现双向绑定,您可以添加一个具有相同名称的@Output属性,后跟Change,并在发生更改时发出事件:

@Input() thing: any;
@Output() thingChange = new EventEmitter();

setNewObject(){
  this.thing = { name: "world", nmb: 10 };
  this.thingChange.emit(this.thing);
}

如果使用双向绑定语法,则更改将反映到父组件:

<child2 [(thing)]="thing"></child2>

有关演示,请参见this stackblitz


如果要防止子组件修改原始对象,则应绑定对象属性而不是对象本身:

@Input() thingName: string;
@Input() thingNmb: number;
<child [thingName]="thing.name" [thingNmb]="thing.nmb"></child>

答案 1 :(得分:3)

是的,FingerprintManagerAngular Change Detection流到parent,但是您遇到的情况与child Object无关。由于referenceparent中的共享对象指向相同的child,因此它将在两个组件中都进行更新。

无论何时通过子组件进行任何更改,共享对象也会在父组件中进行更改,并且Angular将检测到更改并触发UI更新。

但是,与原始数据类型的情况不同。您认为对于原始数据类型是正确的。万一原始数据类型的更改从父级移动到子级,反之亦然。

这是相同的演示-https://stackblitz.com/edit/angular-1wusrc

答案 2 :(得分:1)

将更改检测策略设置为ChangeDetectionStrategy。默认情况下,角度通常会触发更改检测,是的,它将起作用。

将其设置为ChangeDetectionStrategy.OnPush,您将看到不同的行为。

此设置是在组件注释中配置的:

@Component({
    selector: 'my-awesome-component',
    templateUrl: './my-awesome-component.html',
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class MyAwesomeComponent{

}

编辑:我只是尝试在您的堆栈闪电中将ChangeDetectionStrategy更改为OnPush,而更改仍在反映。我只是再次阅读了文档,显然总是将其更新的原因是因为按钮上的click事件触发了更改检测,并且更改检测从子级触发到父级。因此,您可以说更改检测像html事件一样冒泡到根。

答案 3 :(得分:1)

双向数据绑定是event绑定和property绑定的组合类似于香蕉的语法-其中[(ngModel)]是{{1}的组合}和[ngModel]事件

当模型名称后跟(ngModelChange)单词angular会认识到这将是两种方式的数据绑定并使它像这样工作时,就会出现Change一词的神奇之处

进入Change组件Child是通过@Input()绑定将数据传递给子对象的一种方式,而property是从子对象向父对象发送数据的一种方式与@Output()绑定一样-因此要实现双向绑定,您需要两者都绑定-查看下面的示例

event

在上面的代码中,我们具有getModelList: any[]; @Output() modelListChange: EventEmitter<any[]> = new EventEmitter<any[]>(); @Input() get modelList(): any[] { return this.getModelList; } set modelList(value) { this.getModelList = value; this.modelListChange.emit(this.getModelList); } 属性和modelList属性,并具有两个绑定的组合,因此我们可以以modelListChange的身份访问modelList属性,这就是您的双向绑定属性

从父级访问-[(modelList)]="value"现在将基于两种方式的数据绑定来更新父级属性-确保您正确拼写<multi-dropdown [(modelList)]="value"></multi-dropdown>也是区分大小写的

希望这对您有帮助-谢谢您编码愉快!!