【问题标题】:Ng-repeat one-time binding and "track by" changeNg-repeat 一次性绑定和“跟踪”更改
【发布时间】:2018-10-01 10:15:16
【问题描述】:

我们的网络应用使用 ngRepeat 来显示项目列表。数组和它的对象永远不会改变,但里面的对象的值可以被用户修改。

我们为每个项目生成一个唯一的 trackId。每次项目的值更改时都会更新此 trackId。

我们还使用一次性绑定语法来减少页面上的观察者数量(因为它可以迅速攀升至数千)。

但是,这种组合似乎并没有真正起作用;如果项目的 trackId 更改但对象的引用保持不变,则项目不会重新渲染。

来自 angularJS 文档:

自定义表达式:可以使用任何 AngularJS 表达式 计算跟踪 ID,例如使用函数或使用 集合项目的属性。 item.id 跟踪的项目中的项目是 当项目具有唯一标识符时的典型模式,例如数据库 ID。 在这种情况下,对象身份无关紧要。两个对象是 只要它们的 id 属性相同,就被认为是等效的。 跟踪 通过唯一标识符是最高效的方式,应该使用 尽可能。

如果是这样,为什么修改trackId时item没有被销毁并重新创建?

例如:

$scope.friends = [
    {name:'John', age:25, id: 'John-25'},
    {name:'Mary', age:40, id: 'Mary-40'},
    {name:'Peter', age:85, id: 'Peter-85'}
];

$scope.change = function(i) {
    var f = $scope.friends[i];
    f.age = Math.floor(Math.random() * 100);
    f.id = f.name + '-' + f.age;
};

 <div ng-repeat="friend in friends track by friend.id">
    <div ng-bind="'Track id: ' + friend.id"></div>
    <div ng-bind="'Regular binding:' + friend.age"></div>
    <div ng-bind="::'One-time binding:' + friend.age"></div>
</div>

<button ng-click="change(0)">Change John's age</button>
<button ng-click="change(1)">Change Marys's age</button>
<button ng-click="change(2)">Change Peters's age</button>

在这个演示中,我希望当 trackId 更改时对象会被销毁,并且应该使用新的一次性绑定值重新渲染元素。

https://plnkr.co/edit/Lklq3ZNDUuggjgwmkoxj?p=preview

是否有人对解决此问题的方法有任何建议?出于性能原因,我们绝对不能删除一次性绑定。我还研究了 angular-bind-notifier 但这将需要更新重复中的每个绑定,因为它不能针对特定的行。

谢谢

【问题讨论】:

    标签: angularjs angularjs-ng-repeat angular1.6 angularjs-track-by one-time-binding


    【解决方案1】:

    保持每个friend 上的id 不变。

    如果id 真的只是每个朋友的 ID,为什么需要更改?如果您将该属性用于更多而不是 ID,则可以考虑在对象上添加一个新属性并保持 ID 不变。

    如果您不想这样做,您可以随时创建一些帮助函数,将当前朋友的id-value 存储在带有id 键的字典中。然后,您可以通过 friend.id 更新或检索存储在该朋友 ID 中的值。

    【讨论】:

      【解决方案2】:

      ng-repeat 在内部使用$watchCollection,这是对数组的浅层监视,因此更改其中一个数组项的属性不会导致ng-repeat 更新。这里的文档有点误导。

      正如您所猜测的,您需要更改对象引用。切换 id 后,用浅拷贝替换对象。这将导致$watchCollection 检测到更改,然后ng-repeat 将因id 更改而替换该项目。

      $scope.friends = [
          {name:'John', age:25, id: 'John-25'},
          {name:'Mary', age:40, id: 'Mary-40'},
          {name:'Peter', age:85, id: 'Peter-85'}
      ];
      
      $scope.change = function(i) {
          var f = $scope.friends[i];
          f.age = Math.floor(Math.random() * 100);
          f.id = f.name + '-' + f.age;
      
          $scope.friends[i] = Object.assign({}, $scope.friends[i]);
      };
      

      更新的插件: https://plnkr.co/edit/s2ztGQ?p=preview

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-08-20
        • 1970-01-01
        • 2015-06-16
        • 2014-07-17
        • 2015-03-29
        • 2023-04-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多