javascript - 如何强制 ngRepeat 不通过引用进行比较?

标签 javascript angularjs angularjs-ng-repeat

在指令中,我使用 ngRepeat从作用域上的参数化函数获取其项目。

简单来说,它看起来像这样:

<div data-ng-repeat="data in containerItems">
    <div data-ng-repeat="myItem in getItems(data) track by myItem.Id">
        <!-- some content -->
    </div>
</div>

我的问题是我似乎无法摆脱以下异常:

Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!

据我所知,根据其他几个问题(例如 thisthis ),ngRepeat 似乎认为每次重新请求这些项目时都会更新它们,导致它提示另一个消化周期,最终以太多连续的消化周期而结束并放弃。

特别是,one comment按用户g00fy对我来说很有洞察力:确实,我正在使用 lodash_.map function生成由 ngRepeat 显示的项目列表,从而在每次 ngRepeat 重新请求其项目时创建新的对象实例。

起初,我认为可以通过将项目生成函数的返回值保存到作用域上的变量中来解决这个问题。这消除了上述错误。

不幸的是,这对我来说不是一个合适的解决方案,因为范围由使用 ngRepeat 的指令的多个实例共享。我确实需要每个 ngRepeat 使用适当的参数从生成函数中检索项目。

一开始,我使用的是

track by $index

但我也尝试过类似的事情

track by myItem.Id

我曾希望这会强制 ngRepeat 假设仅当 ID 更改时该项目才发生更改。然而,这一切似乎都不能阻止上述异常的发生。

有什么方法可以强制 AngularJS 在其发生更改时仅考虑 ngRepeat 中更改的项目,而不是实例?

从结构上来说,getItems(data) 的返回值似乎可以保存在 data 上。但是,我正在开发的应用程序框架中的代码(这意味着应用程序的许多模块依赖于它的行为,并且不得更改)将直接采用包含 data< 的对象图 并将其发送到服务器端后端。因此,data 不是计算运行时数据的正确位置。


为了提供更完整的示例,getItems 函数大致如下所示:

$scope.getItems = function (data) {
    var itemSet = itemSets[data.itemSetId];
    if (itemSet.customItems) {
        return itemSet.customItems.slice(1);
    } else {
        return _.map(standardItems.slice(1), function (si) {
            return {
                Id: si.code,
                Name: si.Description + ' ' + si.Owner
            };
        });
    }
};

此处的具体细节不相关。重要的是,我根据参数 data 中的某些内容从其他地方检索项目,然后这些项目的格式可能需要转换为由我的 处理的规范格式ngRepeat-ed 模板。

最佳答案

  1. 如果 getItems(data) 永远不会改变,您可以使用一次性绑定(bind):ng-repeat="a in::getItems(data)"
  2. 如果它发生变化,您应该将其结果存储在 $scope 中并手动更新 - 这可能是最好的方法。在 ng-repeat 中使用方法是一种不好的风格,并且很可能会在以后导致性能问题。所以,这看起来像:
<div data-ng-repeat="myItem in myItems track by myItem.Id">
$scope.myItems = getItems(data);
//somewhere you need to update myItems -- can be not easy
  • 您的问题是您的 getItems 不应该创建对象,因此您可以通过缓存对象或完整结果来修复它(请参阅 Deblaton 答案),但这通常不好。所以,这看起来像:

    <div data-ng-repeat="myItem in getItems(data) track by myItem.Id">
    
    $scope.objectCache = {};
    $scope.getItems = function (data) {
        var itemSet = itemSets[data.itemSetId];
        if (itemSet.customItems) {
            return itemSet.customItems.slice(1);
        } else {
            return _.map(standardItems.slice(1), function (si) {
                if (!objectCache[si.code]) { 
                    objectCache[si.code] = {
                       Id: si.code,
                       Name: si.Description + ' ' + si.Owner
                    }; 
                }
                return objectCache[si.code];
            });
        }
    };
    
  • 关于javascript - 如何强制 ngRepeat 不通过引用进行比较?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47769769/

    相关文章:

    AngularJS:指令 Controller 中的 $transclude local 和链接函数中的 transclude 参数之间有区别吗?

    javascript - AngularJS:重置 angular.element css 更改

    angularjs - Angular 中的 select 和 ng-repeat 问题

    javascript - webkitAnimationEnd 在开始时触发

    c# - 如何使用 URL 将数据从 javascript 发送到 ASP.NET MVC Controller

    当字符串中存在重复字符时,Javascript-split() 不起作用

    javascript - 如何暂停网络 worker

    Angularjs,使用 data-ng-controller 和 ng-controller

    javascript - 使用 ng-bind 在 Angular 中无限循环

    javascript - 如何衡量 Angular.js 应用程序(而非 REST 服务)的性能