阻止$scope变量副本侦听其原始副本
Prevent $scope variable copy from listening to its original
在我的AngularJS应用程序中,我通常使用$rootScope
传递数据。在各种状态下,我会在必要时操纵将它们拉入$scope。但由于$scope具有原型继承,我想这只是为了可读性,而不是其他什么。在我的应用程序中,有以下变量。。。
$rootScope.list // object
$rootScope.list.items // array
$rootScope.additions // array
$rootScope.cart // object
$rootScope.cart.items // array
在我开始之前,这通常是以伪代码进行布局的。所以,如果它不正确,那没关系。我在寻找一个概念上的理解。
起初,推车是空的。查看list.items
并将各个列表项复制到cart.items
数组中。这非常有效,直到我们开始讨论具有唯一additions
的重复项。
比方说,我想有两个相同的项目,除了一个项目有不同的添加(购物车项目有一个数量属性,而不是列表项目)。
$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中继器中有重复项。我通过在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变量从一个地方复制到另一个地方时,它表面上是通过引用传递的。
所以,我的下一个想法是尝试使用一个带有隔离作用域的指令。但我很快就意识到我的逻辑是错误的。虽然隔离作用域可以为我提供单向数据绑定,但这并不是我所希望的方向。指令的作用域父级仍然可以设置值。
理想情况下,我想做的是将list.items任意添加到cart.items。但任何来自同一列表项的cart项,我都希望彼此解除绑定。因此,一个副本中的添加可能与另一个副本的添加不同实现这一目标的最佳方式是什么我有一种感觉,使用$rootScope
在我的应用程序中的状态之间传递数据可能是一个糟糕的决定,尽管这是我找到的最快的方法。
您正在寻找的是角度副本。
https://docs.angularjs.org/api/ng/function/angular.copy
有几种方法可以使用,你会在文档中看到,但我和我的同事发现使用可选的"destination"选项更好。
就是这样工作的
首先设置你的新目标阵列。
var newArray = [];
然后你用它作为角度复制的目的地
angular.copy(firstArray, newArray);
好了,就这么简单!
现在,您的新阵列将不再连接到原始阵列。
我也会考虑使用工厂作为代码的服务,而不是使用rootScope。学习这一点将大大提高您的生产力,并使您的代码更加可读和用户友好。这是一篇关于它的好文章。
http://tylermcginnis.com/angularjs-factory-vs-service-vs-provider/
编辑
正如有人在评论中提到的那样,这确实是一个深度复制。这意味着它将复制数组内部的所有子对象和数组。
当您编辑第一个购物车项目的additions
时,您实际上编辑了第一个和第三个购物车的additions
,因为它们是相同的。
当你创建第三个购物车项目时,你可以复制第一个的属性:
var newCartItem = {};
newCartItem.name = firstCartitem.name;
newCartItem.quantity = firstCartitem.quantity;
// Do not point to the other array, instead create a new one and copy over
newCartItem.additions = [];
for (var i = 0; i < firstCartitem.additions.length; i++) {
newCartItem.additions.push( firstCartitem.additions[i] );
}
// Now you can add anything to the new cart item without editing the first one
- 使用 jQuery 的 .on 函数如何获取事件的原始元素
- 使用jQuery从原始页面内容创建iframe
- 从客户端获取修改后的对象,并将其与服务器上的原始对象组合
- 我如何制作一个JS函数,它可以从相似的原始颜色双向更改为某个颜色
- 查找仅适用于原始图像的图像放大算法的名称
- 如何在使用Javascript浏览网站时处理原始窗口
- markrwithlabel.js(第三方)原始文件链接断开
- 处理一个JSON文件;完全相同的副本不是
- 在Javascript中重新分配对象变量时,原始对象会发生什么
- 如何在玩TimelineMax(GSAP)后重置原始位置
- 阻止$scope变量副本侦听其原始副本
- 拖动原始图像时打印图像的副本
- 删除原始对象,同时在 JavaScript 中保留它的副本
- 保持原始数组不变,更改函数中的本地副本
- 创建数组的副本并操作原始数组
- 拖动形状,但保留原始形状的副本
- 从数组的副本中删除项,而不从原始数组中删除项
- 如何替换数组元素而不修改原始数组并创建副本
- HTML5拖放在目标中创建原始副本
- 如何复制HTML文档并根据所选内容编辑副本,而不更改原始文档