javascript - 防止 $scope 变量副本监听其原始内容

标签 javascript angularjs angularjs-scope

在我的 AngularJS 应用程序中,我通常使用 $rootScope 传递数据。在各种状态下,我会在必要时将它们拉入 $scope 中。但由于 $scope 具有原型(prototype)继承,我认为这只是为了可读性,而不是其他。在我的应用程序中,有以下变量...

$rootScope.list // object
$rootScope.list.items // array
$rootScope.additions // array
$rootScope.cart // object
$rootScope.cart.items // array

在开始之前,这通常是用伪代码来阐述的。所以,如果不正确,也没关系。我正在寻找概念性的理解。

一开始,购物车是空的。您查看 list.items 并将各个列表项复制到 cart.items 数组中。这非常有效,直到我们开始讨论具有独特添加的重复项目。

假设,我想要 2 个相同的商品,但其中一个商品具有不同的添加内容(购物车商品具有数量属性,而不是列表商品)。

$rootScope.cart.items = [
   {
      name: 'listItem1',
      quantity: 3,
      additions: ['addition1']
   }, {
      name: 'listItem2',
      quantity: 1,
      additions: ['addition2']
   }, {
      name: 'listItem1', // same as cart.items[1], but additions has diff values
      quantity: 1,
      additions: ['addition1','addition2']
   }];

首先,AngularJS 提示,因为我的 ng-repeater 中有重复项。我通过在 ng-repeat 指令中附加 track by $index 解决了这个问题。这也是我看到的第一个危险信号,告诉我我做错了什么。

我的第一个想法是创建一个临时 cartItem,任意添加其添加项,然后将其推送到 $rootScope.cart.items[] 上。但是,当需要将第三个购物车项目插入购物车(这是第一个列表项目的另一个副本)时,它会覆盖第一个购物车项目的 additions[] 。因此,$rootScope.cart.items 看起来像这样:

$rootScope.cart.items = [
   {
      name: 'listItem1',
      quantity: 3,
      additions: ['addition1','addition2']
   }, {
      name: 'listItem2',
      quantity: 1,
      additions: ['addition2']
   }, {
      name: 'listItem1', // same as cart.items[1], but additions has diff values
      quantity: 1,
      additions: ['addition1','addition2']
   }];

从这个结果来看,将 $rootScope 变量从一个地方复制到另一个地方时,表面上是按引用传递的。

所以,我的下一个想法是尝试使用具有隔离范围的指令。但我很快就意识到我的逻辑是错误的。虽然隔离范围可以为我提供单向数据绑定(bind),但它并不是我所希望的方向。该指令的父范围仍然可以设置值。

我理想的做法是将 list.items 任意添加到 cart.items。但是来自同一列表项的任何购物车项目,我希望彼此解除绑定(bind)。因此,一个副本中的添加可以与另一副本中的添加不同。 实现这一目标的最佳方法是什么?我有一种感觉,使用 $rootScope 在我的应用程序中的状态之间传递数据可能是一个糟糕的决定,尽管它这是我发现的最快的方法。

最佳答案

Angular 副本正是您所寻找的。

https://docs.angularjs.org/api/ng/function/angular.copy

有几种使用此方法的方法,您将在文档中看到,但我和我的同事发现使用可选的“目标”选项更好。

这就是它的工作原理

首先设置新的目标数组。

var newArray = [];

然后将其用作 Angular 复制中的目标

angular.copy(firstArray, newArray);

就是这样,就是这么简单!

现在您的新阵列将不再连接到原始阵列。

我还会考虑使用工厂作为代码的服务,而不是使用 rootScope。学习这将大大提高您的工作效率,并使您的代码更具可读性和用户友好性。这是一篇关于它的好文章。

http://tylermcginnis.com/angularjs-factory-vs-service-vs-provider/

编辑

正如有人在评论中提到的,它确实是一个深拷贝。这意味着它将复制数组内的所有子对象和数组。

关于javascript - 防止 $scope 变量副本监听其原始内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28638392/

相关文章:

javascript - 访问指令的隔离范围与嵌入的内容

javascript - 如何使用angular指令从html获取数组?

javascript - AngularJS:有条件的 ng 类,一个选项有多个匹配项。

javascript - angularjs ns-显示逻辑流程

javascript - 如何保存ArrayBuffer?

javascript - FileReader onload 只能在 Firefox 中第二次运行?

javascript - jQuery 可排序/禁用选择问题

javascript - 将值从一个文件传递到另一个 javascript

javascript - JSON 和 Angular 。按 ID(而不是按索引)过滤数组

angularjs - 模块注入(inject)与单一应用程序