简体   繁体   English

单向绑定组件中的对象或数组的Angular方法是什么?

[英]What is the Angular way to one-way bind an object or array in a component?

I am creating a component to edit an array of simple objects. 我正在创建一个组件来编辑简单对象的数组。

According to the Angular 1.7.2 documentation , components should use one-way ( < and @ ) bindings where possible, and use & bindings for output callbacks. 根据Angular 1.7.2文档 ,组件应在可能的情况下使用单向( <@ )绑定,并在输出回调中使用&绑定。 It states: 它指出:

For components however, only the component that owns the data should modify it, to make it easy to reason about what data is changed, and when. 但是,对于组件而言,只有拥有数据的组件才可以对其进行修改,以使其易于推断出哪些数据已更改以及何时更改。

Regarding input objects and arrays, it states specifically: 关于输入对象和数组,它特别声明:

The general rule should therefore be to never change an object or array property in the component scope. 因此,一般规则是永远不要在组件范围内更改对象或数组属性。

My component accepts an array of objects as input, provides a way to edit the properties on these objects, and insert and delete objects to the array. 我的组件接受对象数组作为输入,提供一种编辑这些对象的属性以及将对象插入和删除到数组的方法。 The component needs to update its view if the object array is changed elsewhere. 如果对象数组在其他位置更改,则组件需要更新其视图。 The component does not own the data it accepts as input. 该组件不拥有它接受作为输入的数据。

I've defined the bindings of the component as follows: 我定义了组件的绑定,如下所示:

{
    objects: "<",
    addObject: "&",
    deleteObject: "&",
    updateObject: "&"
}

Considering that the objects data should not be changed by the component, the component must make a local copy of the objects during $onChanges . 考虑到组件不应该更改objects数据,因此组件必须在$onChanges期间创建objects的本地副本。 Changes to the local copy are then propagated to the parent via the callbacks. 然后,通过回调将对本地副本的更改传播到父级。

However, this creates a disconnect between the local copy and the original data. 但是,这会在本地副本和原始数据之间造成断开连接。 $onChanges is only triggered if the objects reference itself is reassigned. 仅当objects引用本身被重新分配时,才触发$onChanges

The solution to that is to place a watch on objects with object equality that triggers the creation of the local copy. 解决方案是对具有对象相等性的objects进行监视,以触发本地副本的创建。 This seems counter to what components are supposed to do, and I've seen elsewhere that $watch used in components is seen as a crutch and/or smelly design. 这似乎与组件应该做的事情背道而驰,而且我在其他地方$watch ,组件中使用的$watch被视为拐杖和/或臭气熏天的设计。

This plunker demonstrates the issue. 这个小伙子演示了这个问题。

What is the correct way to implement this design? 实施此设计的正确方法是什么?

I believe the documentation you are referencing is talking specifically about changing an object or array property , as this change will not be reflected in the parent scope. 我相信您所参考的文档专门讨论更改对象或数组属性 ,因为此更改不会反映在父作用域中。 I don't see any issue with a component mutating the objects passed in. 我看不到组件使传入的对象发生变异的任何问题。

For your example - if you pass an array via the "objects" binding into your component - and then your component sets its "objects" property to a different array - the parents original array will not reference this change. 对于您的示例-如果您通过绑定到组件的“对象”传递一个数组-然后您的组件将其“对象”属性设置为其他数组-父级原始数组将不会引用此更改。

The difference to = is that the bound properties in the component scope are not watched, which means if you assign a new value to the property in the component scope, it will not update the parent scope. 与=的区别在于,不监视组件范围内的绑定属性,这意味着,如果为组件范围内的属性分配新值,则不会更新父范围。 Note however, that both parent and component scope reference the same object, so if you are changing object properties or array elements in the component, the parent will still reflect that change. 但是请注意,父级和组件范围都引用同一对象,因此,如果要更改组件中的对象属性或数组元素,父级仍会反映该更改。 The general rule should therefore be to never change an object or array property in the component scope. 因此,一般规则是永远不要在组件范围内更改对象或数组属性。

As for me the answer would be very simple - components are not ment to perform data manipulation. 对于我来说,答案将非常简单-组件不执行数据操作。 You told that you created component to edit array? 您告诉您创建了要编辑数组的组件? Then this is where you can start using services. 然后,您可以在这里开始使用服务。 Each service is a singleton, therefore you can reference the same object property from every place you did inject it. 每个服务都是单例,因此您可以在注入它的每个位置引用相同的object属性。 Checkout what AngularJS team says about services 结帐什么 AngularJS团队说,有关服务

Managing data via scopes is reckless. 通过范围管理数据是鲁ck的。 Scopes can easily become corrupted or dirtied by other controllers, directives, models and the like. 范围很容易被其他控制器,指令,模型等损坏或弄脏。 It gets messy quickly. 它很快就会变得混乱。 Having a central channel (in this case a service) ... not only is a lot cleaner - it's also much easier to manage as the application grows. 拥有中央通道(在这种情况下为服务)...不仅更清洁-随着应用程序的增长,它也更易于管理。 Lastly - it keeps your code modular (something Angular excels at). 最后-它使您的代码保持模块化(Angular擅长的事情)。 Should you ever need that service for another project, you don't need to dig through scopes, controllers, filters, etc. to find relevant code - it's all there in the service! 如果您需要为另一个项目使用该服务,则无需深入研究范围,控制器,过滤器等,即可找到相关的代码-服务中所有内容都在其中!

Speaking about components - first of all they are HTML directives. 谈到组件-首先,它们是HTML指令。 Component should have HTML template. 组件应具有HTML模板。 The purpose of a component is to reflect some data received from the parent scope in its template and pass some event or data (which is a result of user interaction) to the higher level through callback. 组件的目的是在其模板中反映从父级作用域收到的一些数据,并通过回调将一些事件或数据(这是用户交互的结果)传递给更高级别。 If you need an external logic in the component - better delegate it to a service. 如果您需要组件中的外部逻辑-最好将其委托给服务。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM