ng-repeat内的angularjs ng-model表现不佳

时间:2014-07-09 11:06:11

标签: javascript performance angularjs

我在以下情况中遇到角度问题:

<div ng-repeat="a in array">
  <input ng-model="something">
</div>

我在我的控制器中编写了代码,ng-click上的代码将数组更改为具有不同的对象集。问题是,如果数组具有相当数量的对象,则点击不像我希望的那样响应(短暂延迟)。

经过一番调查后,我发现在$digest更改数组后,ng-click需要很长时间。所以我创建了这个short test code来重现它。

真正的应用场景是这样的:我有一个表,其中每一行代表一个可编辑的对象,每个对象都有许多我想要编辑的不同字段。这样,每当我点击表格中的一行时,就会有另一个html,其中ng-repeat的所有input在我的对象的属性上都有{{1}}个。

有没有人知道如何提高效率?

由于

3 个答案:

答案 0 :(得分:3)

如果我正确理解了您的问题,那么您遇到的ui阻塞会让您的体验变得不稳定。您的收藏中有多少件物品?如果我没有弄错,重复是同步的,如下所示: https://github.com/angular/angular.js/blob/master/src/ng/directive/ngRepeat.js#L361

因此,您无法在不阻止UI的情况下呈现数百/数千/等的记录,并且实现了ng-repeat。唯一的解决方案是使用异步解决方案并一次渲染一些集合。不幸的是,我没有看到异步重复(一个可能存在,你应该寻找它或自己实现并交给我们)。

幸运的是你可以使用ng-repeat的limitTo属性作为类似的东西。如果你有limitTo:num,其中num = 5,那么只会渲染前5个记录。如果你设置num = 7那么它将保留5个已经渲染的记录,并且只渲染第6个记录和第7个记录。

因此要渲染几千条记录,你需要这样的东西来异步改变limitTo:

<div ng-repeat="a in array | limitTo:tick">

...

var repeatAsyncHack = function() {
    $scope.$digest();
    sum += +new Date() - t;
    if($scope.tick < numOfObjects) {
        $scope.tick+=tickAmount;
        requestAnimationFrame(repeatAsyncHack);
    } else {
        $('#results').prepend(
            $("<div>" + 
              numOfObjects + ' objects test took: ' + sum +
              "ms</div>"));
    }
}

我在http://jsfiddle.net/qrJG3/15/

更新了您的演示版

当然,总的渲染时间要长得多。这样做只是为了让应用程序更具响应性。

如果我误解了你的内容,请纠正我。

答案 1 :(得分:3)

在同一页面上包含太多输入元素通常是个坏主意。这就是专业数据网格编辑器选择在单独的弹出窗口或内联中一次只编辑单个数据行的原因。即使在线使用,物体也会即时注入。

输入元素太重了,在同一页面上没有太多。我在过去做过同样的错误,试图实现一个数据网格,其中所有可编辑字段都是从头开始的输入元素。最重要的是,您必须保持实时角度模型绑定,这会增加性能开销。

在您的情况下,最简单的方法之一是实现一个显示为span元素的指令,直到它被点击并在click事件上交换输入元素。另一种选择 - 同时拥有并切换其可见性风格。后者在角度指令中可能更容易,但可能效率不高。

另请注意您拥有的其他绑定。谈到数据网格,这变得很重要。在Angular 1.3中,您现在可以使用&#34; ::&#34;一次性绑定的语法,这也可能会有所帮助。

答案 2 :(得分:0)

如果您正在动态创建DOM元素,则会有延迟。

如果元素已经在页面上,你只是隐藏它们直到它们的时间通常会快得多。

您可以使用的另一个方面是感觉响应性真实的响应性 - 您可以首先显示一些静态html,然后用实际元素替换它。在创建实际结果的同时,用户将立即获得结果。

修改

让我们将生成的HTML与ng-model

进行比较

使用模型

<div ng-repeat="a in array" class="ng-scope">
   <input ng-model="a.qqqq" class="ng-pristine ng-valid">
</div>

在输入上加上eventhandler。

没有模特

<div ng-repeat="a in array" class="ng-scope">
     <input>
</div>

没有事件处理程序。

您可以使用Angular的调试版本进行深入研究,以实际查看添加ng-model时的最新情况。

- &gt; 之所以花费更多时间是显而易见的 - Angular正在做更多事情。