2013-05-02 18 views
6

我有一個包含兩件事情的角度範圍:AngularJS性能:如何只更新我知道需要更新的範圍?

  • 一個巨型表用10k行,需要一個第二渲染在它上面以固定覆蓋標題欄
  • 一些小的額外信息

根據您向下滾動頁面/表格的距離,我必須更新標題中的一個小信息位;你可以把它看作是一個%計數器,你已經滾動了多少。

爲了得到當前滾動位置,我已經寫了指令(你也可以找到它here):

app.directive "setWindowScroll", -> 
    restrict: "E" 
    scope: 
    setVariable: "=" 

    link: (scope) -> 
    $(window).scroll -> 

     scope.$apply -> 
     scope.setVariable = $(window).scrollTop() 

我的問題是,這使得在表中各地滾動U * nsuably慢 * 。這是因爲我用我的指令寫入的可讀性是在範圍內的額外信息中,並且改變這似乎導致角度變髒 - 當調用我的$apply時,檢查整個表的變化。

我知道這個滾動不會改變我的表中的任何內容,並且想要限制我的$apply影響我網站的標題部分。

如何讓角度不是髒檢查表?

回答

3

Angular在一個名爲digest的進程下進行髒檢查。當您撥打$scope.$digest()時,它會傳播到$scope的每個子範圍。要通知角度變化你通常做一個$scope.$apply()。在$ apply()角度結束時在根作用域上執行一個摘要,這會在應用程序中的每個作用域上觸發一次挖掘。所以爲了避免在你的範圍內使用大表作用域進行摘要,你應該確保它不是額外信息範圍的孩子,而不是做一個$ scope。$ apply()在你的指令中,你可以做一個$範圍。$摘要()。這可能有點令人困惑,所以我製作了一個試圖展現其差異的笨蛋。打開控制檯,並看到滾動事件和按鈕的區別點擊:

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

// 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(); 
}) 

當這一切都說過,這是一個非常不尋常的事情 - 也許不是一個號碼是個好主意(角度沒有很好地適應數千個元素,你不能使用任何角度事件指令(ngClick等),因爲它們都被包裝在$ apply中) - 但是如果你不能在服務器上呈現表這邊你可以試試這個。

+0

不得不在新窗口中打開一個滾動條來獲取Firefox中的滾動條:http://run.plnkr.co/4CAAfTuXNmgfGdql/ – 2013-05-02 15:02:27

+0

新窗口鏈接不適用於我。 [This](http://beta.plnkr.co/45gKhAIt0DrozS7f0Bz2)和http://run.plnkr.co/plunks/45gKhAIt0DrozS7f0Bz2/。 – nh2 2013-05-03 01:31:20

+0

感謝您解答這個問題的出色答案。我把我的頭文件放到它自己的範圍內,並且確實使用'$ digest'而不是'$ apply'修復了我的問題。然而,你最後說的話是非常正確的 - 無法使用任何*調用'$ apply'的東西不可行,而且非常有限。由於我的表大多不會改變,我會嘗試在瀏覽器中呈現表,但沒有數據綁定(通過在創建後分離觀察者,編寫自定義的'ng-repeat'類指令或使用更原始的,僅用於表格的非綁定模板引擎)。 – nh2 2013-05-03 01:55:56

0

我想知道這是否也可以做,但是 - 無論 - 你可能想考慮不一次繪製整個表。

取而代之的是根據當前滾動位置+上下一些緩存行限制它(以及Angular-world中相關數據/控制器的數量)。您仍然可以將所有數據保留在客戶端的數組中,但只能在Angular中隨時暴露一小部分數據。

這樣做的一種方法可能是在角度世界中使用ng-repeat渲染一個小陣列,然後根據滾動位置從大的無角陣列添加和移除此小角陣列中的元素。

這樣Angular只知道你的數據的一小部分,並且應該渲染得更快。我認爲這應該在一般情況下工作得很好,因爲對於不需要維護DOM樹和渲染10k行的瀏覽器來說,它也少得多。

+0

一般而言,你是對的,我也想過這個,但在這種情況下,我需要複製一個現有的具有相同表格的UI,只要我不觸發這個意外的髒檢查,它確實非常活潑所有的時間都是通過更新表格之外的東西。 – nh2 2013-05-02 09:55:23