【问题标题】:Array reference is reused instead of cloned/copied - multiple instances of angular-bootstrap-nav-tree重用数组引用而不是克隆/复制 - angular-bootstrap-nav-tree 的多个实例
【发布时间】:2014-01-02 15:54:04
【问题描述】:

我在我的 AngularJS 应用程序中使用 Nick Perkin 的树指令 (https://github.com/nickperkinslondon/angular-bootstrap-nav-tree)。

我想在两个不同的 UI Bootstrap 选项卡中显示基于相同数据的两棵树。树会根据过滤器显示不同的元素。

我的问题是,当我展开一棵树中的一个元素,然后切换到包含另一棵树的选项卡时,另一棵树的元素也会展开,反之亦然。

我猜这个问题在某种程度上与范围有关,但是该指令的编写方式是创建一个隔离的范围。 (至少我是这么认为的。)

当使用两个不同的数据数组时它工作正常,但奇怪的是,当我使用数据数组的真实副本(通过使用arrayB = arrayA.slice(); 复制)时,它不再工作并且展开/折叠状态等是再次在两个树实例之间共享。

是我的错误还是我必须通过某种 treeId 扩展指令?如果是这样,我该怎么做?

Plunkr 示例:http://plnkr.co/edit/J0WIOkxEy7l0x9b5mqi4

【问题讨论】:

  • 请以jsbin.com 之类的方式举例。不看代码就很难调试。在不包含代码的情况下发布代码问题也是违反 SO 政策的。
  • Array.slice() 创建一个浅拷贝。
  • @m59 我加了一个例子。
  • @zeroflagL 我的主要问题是我希望两棵树都基于相同的数据,复制的东西只是我在试图找到问题时玩弄的东西。
  • 隔离范围意味着指令可以处理不同的数据。

标签: javascript angularjs twitter-bootstrap tree angularjs-directive


【解决方案1】:

代替slice() 使用这个:$scope.data2 = angular.copy($scope.data);

问题在于slice() 是一个浅拷贝,因此您在指令的两个实例中使用相同的对象引用。 angular.copy() 很深,所以两者都是完全独立的。 Live demo here (click). 看到现在菜单是分开操作的。

这是一个传递相同数组的示例,但让指令本身复制并使用它。您可以进一步扩展它以使用 $watch 来查看原始数组,但始终使用副本进行实际工作。 Live demo (click).

【讨论】:

  • 正如我在评论中所写的,Array.slice() 创建一个浅拷贝,而 angular.copy() 创建一个深拷贝。 uid 无关紧要。 OP 的目标是为两棵树使用 same 数组。这是不可能的。除此之外,您的解决方案就是要走的路。
  • 好的,我想我必须让它像这样工作,并找到一种方法来保持我的两个树数据副本一致。谢谢!
  • @muenchdo 在这种情况下,值得注意的是,您可以将同一个数组传递给指令两次,然后让指令监视该数组,但在实际工作中使用副本。
  • @zeroflagL 我更新了我的答案。谢谢 =D 我想我想太多了。
【解决方案2】:

m59 的答案是正确的——如果您需要 2 棵树,您应该使用“树数据”的深层副本。您提供的树数据不仅仅是树的定义——它还将用于跟踪它的状态——树为每个分支添加一个“扩展”属性和一个“选定”属性。因此,如果您共享树数据,那么“扩展”状态也会被共享。如果您想要两棵具有不同状态的树,那么您需要单独的树数据。

更好的方法可能是将“树数据”与原始数据分开,无论它是什么。使用循环遍历原始数据并从中创建“树数据”的函数。

如果您想让 2 棵树代表一个共同的、共享的数据集,那么您可以使用分支的“branch.data”属性来引用原始数据的元素。也就是说,每棵树都有单独的“树数据”,但两棵树中的分支都指向一些共享数据。

假设,例如,您有一个“人员”列表,并且您想要创建 2 棵树,它们都代表相同的人员列表。

首先,编写一个循环遍历您的人员列表的函数,并生成一个新的树枝列表(“树数据”)。对于每个分支,将“branch.data”设置为指向人员列表中的原始“person”对象。

现在,运行您的函数两次,以生成 2 组单独的“树数据”。结果是两棵树具有不同的状态,但两棵树上的“branch.data”引用了相同的共享数据。

请注意,如果您还使用“branch.data”,则必须小心使用“深度复制”——您可能不想深度复制分支数据(在示例中,这将创建一个副本由 branch.data 引用的每个“Person”对象,这不是你想要的——你想要一个共享引用)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-01-16
    • 1970-01-01
    • 1970-01-01
    • 2021-10-09
    • 2014-01-09
    • 2011-10-19
    • 2017-06-20
    相关资源
    最近更新 更多