在 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());
如果组件没有任何关联怎么办?
那么他们应该通过共享服务进行通信,而不是使用Input
和Output
。
【讨论】:
我不同意循环引用。双向变化检测将有效地等同于与 AngularJS 中的手表的双向绑定,这很好。父级会更新子级,并且(在最坏的情况下)子级中的更改会导致父级中的更改检测触发,但不会进一步更改,然后不会发生其他任何事情。 你是对的。您的代码中会有一个无限循环,这将是运行时的缺陷。这并不意味着循环引用是一件好事。 我认为不会有无限循环。除非我弄错了,否则它相当于在 AngularJS 中使用ng-model
。
你是对的。抱歉,第二条评论应该说“不会有无限循环,也不会是运行时的缺陷”。我似乎无法打字。以上是关于在 Angular 组件中与 @Input 和 @Output 共享数据的主要内容,如果未能解决你的问题,请参考以下文章
处理 Angular 2 中动态创建的组件的 @Input 和 @Output