ngRepeat track by:如何在模型更改时添加事件挂钩?

ngRepeat track by: How to add event hook on model change?

我有一个简单的 ngRepeat,如下所示:

<some-element ng-repeat="singleRecord in arrayOfRecords track by singleRecord.id">
    <!-- stuff -->
</some-element>

arrayOfRecords 从服务器更新,可能包含新数据。

ngRepeattrack by 功能可以计算出何时将新元素添加到数组并自动更新 DOM 而无需更改现有元素。我想挂接到该代码并在有新数据传入或旧数据被删除时执行回调函数。是否可以通过 Angular 轻松做到这一点?

据我所知,有一个 $$watchers 会在某些变量发生变化时触发回调,但我不知道如何破解它。这是正确的方向吗?


注意:我知道我可以手动保存 arrayOfRecords 并在获取它们时将其与新值进行比较以查看发生了什么变化。但是,由于 Angular 已经提供了具有此逻辑的 track by 功能,如果我可以让 Angular 在数组中添加或删除元素时自动触发事件回调,那就太好了.复制 Angular.

中已经存在的逻辑没有意义

也许你可以创建一个指令并将其与 ng-repeat 一起添加,因此指令在创建时(当项目被 ng-repeat 添加时)将发出一个事件,同样当项目被销毁时它会发出另一个事件事件。

这里有一个简单的实现:

.directive('tracker', function(){
  return{
    restrict:'A',
    link:function(scope, el, attr){
      scope.$emit('ITEM_ADDED', scope.$eval(attr.tracker))
      scope.$on('$destroy', function(){
        scope.$emit('ITEM_REMOVED', scope.$eval(attr.tracker))
      });
    }
  }
});

并将其用作:

<some-element 
       ng-repeat="singleRecord in arrayOfRecords track by singleRecord.id"
       tracker="item">

并在父控制器中监听这些事件。

Demo

或者以不同的方式使用函数绑定,而不为此使用隔离作用域。

.directive('tracker', function() {
  return {
    restrict: 'A',
    link: function(scope, el, attr) {
      var setter = scope.$eval(attr.tracker);
      if(!angular.isFunction(setter)) return;
      setter({status:'ADDED', item:scope.$eval(attr.trackerItem)});


      scope.$on('$destroy', function() {
         setter({status:'REMOVED', item:scope.$eval(attr.trackerItem)});
      })
    }
  }
});

Demo


上面的那个是针对你的问题的,因为没有其他内置的方法,请注意,如果你真的要找出项目 added/removed,你也可以在你的控制器中通过 diffing 来完成2个列表。您可以尝试像 _.unique 一样使用 lodash api 甚至简单的循环比较来查找结果。

  function findDif(oldList,newList){
       return {added:_.uniq(newList, oldList), removed:_.uniq(oldList, newList)};
 }

Demo

您可以将其更改为:

<div ng-model="arrayOfRecords">
<some-element ng-repeat="singleRecord in arrayOfRecords track by singleRecord.id">
    <!-- stuff -->
</some-element>
</div>

一旦 arrayOfRecords 发生变化,模型也会发生变化。