AngularJS性能:如何只更新我知道需要更新的作用域



我有一个角作用域包含两个东西:

  • 一个大表,有10k行,渲染
  • 需要一秒钟
  • 一些小的额外信息在它的顶部固定覆盖标题栏

根据你向下滚动页面/表的程度,我必须更新标题中的一个小信息位;你可以把它想象成一个%计数器,显示你滚动了多远。

为了得到当前的滚动位置,我写了一个指令(你也可以在这里找到它):

app.directive "setWindowScroll", ->
  restrict: "E"
  scope:
    setVariable: "="
  link: (scope) ->
    $(window).scroll ->
      scope.$apply ->
        scope.setVariable = $(window).scrollTop()

我的问题是,这使得滚动在表u*非常慢*。这是因为我用我的指令写的变量在范围内的额外信息中,并且当我的$apply被调用时,改变它似乎会导致角脏检查整个表的变化。

我知道这个滚动永远不会改变我的表中的任何东西,并希望限制我的$apply影响我的网站的标题部分。

如何使角脏检查表?

Angular在一个名为digest的进程下进行脏检查。当您调用$scope.$digest()时,它将传播到$scope的每个子作用域。要通知angular变化,你通常会执行$scope.$apply()。在$apply()的末尾,angular对根作用域做一个摘要,它会触发应用中每个作用域的摘要。因此,为了避免在具有大表作用域的作用域中使用digest on,您应该确保它不是额外信息作用域的子作用域,而不是在指令中使用$scope.$apply(),而是使用$scope.$digest()。这可能有点令人困惑,所以我做了一个柱塞,试图显示差异。打开控制台,查看滚动事件和按钮单击的区别:

http://plnkr.co/edit/45gKhAIt0DrozS7f0Bz2?p =

预览
// this will only cause a digest in the current scope and its children
angular.element($window).bind('scroll',function(){
  $scope.scrollY = $window.scrollY;
  $scope.$digest();
})
// this will cause a digest in every scope
angular.element($window).bind('scroll',function(){
  $scope.scrollY = $window.scrollY;
  $scope.$apply();
})

说了这么多,这是一件非常不寻常的事情——而且可能不是一个好主意,原因有很多(angular不能很好地扩展数千个元素,你不能使用任何angular的事件指令(ngClick等),因为它们都被包裹在$apply中)——但如果你不能在服务器端渲染表格,你可以试试。

我想知道这是否也可能做到,但是-无论如何-您可能要考虑不要一次绘制整个表。

将它(以及angular世界中相关数据/控制器的数量)限制为基于当前滚动位置可见的行+上面和下面的一些缓存行。你仍然可以将所有数据保存在客户端上的数组中,但在任何时候只向Angular公开一小部分数据。

一种方法可能是在angular世界中使用ng-repeat渲染一个小数组,然后根据滚动位置在这个小角度数组中添加和删除元素。

这样,Angular只知道你数据的一小部分,而且渲染速度会快得多。我认为这应该在一般情况下工作得很好,因为它也更少的工作,浏览器不需要维护一个DOM树和渲染10k行。

最新更新