在 Angular 组件中与 @Input 和 @Output 共享数据

Posted

技术标签:

【中文标题】在 Angular 组件中与 @Input 和 @Output 共享数据【英文标题】:Sharing data with @Input and @Output in Angular components 【发布时间】:2019-09-17 12:17:15 【问题描述】:

我不明白为什么一个事件需要从孩子分享给父母 (@Output),而 @Input() 对父母来说可以正常工作。

如果我们想与父组件共享数据而不点击任何按钮,例如@Input,该怎么办?如果组件没有任何关联怎么办?

【问题讨论】:

【参考方案1】:

对于你问题的第一部分,我想详细说明:

我不明白为什么你需要一个事件来从孩子到父母共享数据 (@Output),而 @Input() 对于父母到孩子来说工作得很好。

因为 Angular 有一个从上到下的单向变化检测系统。

这意味着父项中的更改会传播给子项,而不会反过来,设计,使应用程序状态的流程更易于理解。 p>

对于绑定属性(例如用@input 装饰的属性),父级中值(对于基元)或引用(对于对象)的更改将导致更改检测触发,并且子级将使用新值更新或参考。

但是,例如,重新分配子级中的 @input 属性不会更新父级中的引用,因为这会违反上述自上而下的设计。

虽然有一个 decorator 用于输出,但没有从底部到顶部的更改检测,因此必须将这个方向的更改明确告知父级,例如与事件,这正是发生了什么。

补充说明

尽管如此,对子项中绑定属性的更改仍有可能导致在父项中看到更改。当对象引用传递给子对象并且子对象使用该引用改变对象时,就会发生这种情况,因为最终它仍然是 javascript,并且父对象和子对象都引用了同一个对象。 AND 如果有什么东西else 会在父级中触发更改检测,这会更新 DOM 并在屏幕上观察到此突变的效果。

但是,此代码难以理解和调试,而 @output 是声明性且清晰的。

【讨论】:

【参考方案2】:

为什么我们需要一个事件?

因为这可以防止循环引用。如果父级有对子级的引用,而子级有对父级的引用,则它将是循环引用。它还增加了代码的复杂性。如果我正在编写一个“按钮”组件,我不想担心什么样的组件持有我的按钮组件。

如果我们想在不点击的情况下与父组件共享数据怎么办 像@Input 一样的任何按钮?

您可以通过编程方式触发事件。例如,您可以有一个计时器组件,它使用 RxJS interval observable 每 5 秒触发一次事件。

interval(5000).subscribe(() => myOutput.next());

如果组件没有任何关联怎么办?

那么他们应该通过共享服务进行通信,而不是使用InputOutput

【讨论】:

我不同意循环引用。双向变化检测将有效地等同于与 AngularJS 中的手表的双向绑定,这很好。父级会更新子级,并且(在最坏的情况下)子级中的更改会导致父级中的更改检测触发,但不会进一步更改,然后不会发生其他任何事情。 你是对的。您的代码中会有一个无限循环,这将是运行时的缺陷。这并不意味着循环引用是一件好事。 我认为不会有无限循环。除非我弄错了,否则它相当于在 AngularJS 中使用 ng-model 你是对的。抱歉,第二条评论应该说“不会有无限循环,也不会是运行时的缺陷”。我似乎无法打字。

以上是关于在 Angular 组件中与 @Input 和 @Output 共享数据的主要内容,如果未能解决你的问题,请参考以下文章

处理 Angular 2 中动态创建的组件的 @Input 和 @Output

在 Angular 中为动态加载的组件提供 @input

Angular 将 @Input 用于深度嵌套的组件

angular之Input和Output

angular2 在子组件中更改@input 值,然后在父组件中更改此值不起作用

如何在 Input Angular Decorator 中使用 Observable?