为ng-repeat加载大量元素

时间:2014-01-30 12:43:00

标签: javascript performance angularjs optimization angularjs-ng-repeat

我有一个页面需要从API加载数千行(通过AngularJS服务)。我决定一次加载100个,而不是一次完成,ala:

$scope.fetchTransactions = function(page) {
  TransactionService.get($scope.product, page).then(function(response) {
    $scope.transactions = $scope.transactions.concat(response.data.transactions);

    if(response.data.transactions.length > 0) {
      $timeout(function() {
        $scope.fetchTransactions(page + 1);
      }, 1000);
    }
  });
}
$scope.fetchTransactions(1);

一次加载100个交易。在我看来,我有一张表和tr看起来像:

<tr class="fade-in-repeat" ng-repeat="transaction in transactions | orderBy: ['-txid', '-time']>

加载时,浏览器会在此处冻结一秒钟。我该怎么做才能加快速度呢?

**一个交易的样本JSON **

{
  "__v":1,
  "_id":"52e7c99dc22c6f16aee227e7",
  "blockhash":"00000000186a147b91a88d37360cf3a525ec5f61c1101cc42da3b67fcdd5b5f8",
  "blockheight":51741,
  "blockorder":601,
  "blocktime":1271619803,
  "locktime":0,
  "time":1271619803,
  "txid":"0a37858c0d00af40cce12256133d7e743c42ffb345e8826d3e6700c6d0745413",
  "version":1,
  "vin_total":27.34,
  "vout_total":27.34,
  "updatedOn":"2014-01-28T15:15:41.508Z",
  "indexedOn":"2014-01-28T15:15:41.508Z",
  "vout_addresses":[
    "1CQXTdQYwquztA6jry2NjDVfRoizPco5rR",
    "1XPTgDRhN8RFnzniWCddobD9iKZatrvH4"
  ],
  "vout":[
    {
      "n":0,
      "spent_txid":"60417dc3a354910719c32eb3e70f14f971807cbb3a3c6b0b1cccc7b09c838115",
      "value":27.33,
      "scriptPubKey":{
        "reqSigs":1,
        "type":"pubkeyhash",
        "addresses":[
          "1CQXTdQYwquztA6jry2NjDVfRoizPco5rR"
        ]
      }
    },
    {
      "n":1,
      "spent_txid":"77036fa2ac75212be1ce93e8e1008d5cb2bcbb51aa560a5fe29c9c1423bbd00e",
      "value":0.01,
      "scriptPubKey":{
        "reqSigs":1,
        "type":"pubkeyhash",
        "addresses":[
          "1XPTgDRhN8RFnzniWCddobD9iKZatrvH4"
        ]
      }
    }
  ],
  "vin":[
    {
      "_id":"52e7c99dc22c6f16aee227e8",
      "sequence":4294967295,
      "txid":"c0eea97dc593f059f90630839557a5df1c3c8d7b73e01e5c8c01b89764705583",
      "vout":1,
      "meta":{
        "address":"13QaytjPv9cAJbDjGZCKCthxd8kHtSWKHE",
        "amount":27.34
      }
    }
  ]
}

2 个答案:

答案 0 :(得分:2)

使用ng-repeat处理数千行时,角度是个坏主意,因为它会为每个元素添加$ watch,因此会对性能产生直接影响。

所以现在你能做的最好的事情就是与自己的DOM一起工作, 我建议创建自己的指令并使用本机JavaScript API或JQuery迭代元素,这没关系,我也建议使用CreateDocumentFragment进行DOM操作(why是否要使用CreateDocumentFragment )。

示例:

  mainApp.directive("myRepeater", function () {
   var LIST_ITEM = "li";
        return {            
            restrict: "A",
            link: function (scope, element, attrs) {
                var rawElm = element[0];        
                scope.$watch(attrs.source, function(newValue) {
                    if (!newValue || !newValue.length || newValue.length === 0) return;

                    // wipe the previous list
                    rawElm.innerHTML = "";
                    var frag = document.createDocumentFragment();

                    newValue.forEach(function (item) {
                        var listItemNd = document.createElement(LIST_ITEM);
                        var textNd = document.createTextNode("your text");
                        listItemNd.appendChild(textNd);
                        frag.appendChild(listItemNd);
                    });

                    rawElm.appendChild(frag);
                });
            }
        };
    });

答案 1 :(得分:0)

尝试预先过滤它(注入$filter):

$scope.fetchTransactions = function(page) {
  TransactionService.get($scope.product, page).then(function(response) {

    if(response.data.transactions.length > 0) {

      var transactions = $scope.transactions.concat(response.data.transactions);
      $scope.transactions = $filter('orderBy')(transactions, ['-txid', '-time']);

      $timeout(function() {
        $scope.fetchTransactions(page + 1);
      }, 1000);
    }
  });
}

并使用track by

<tr class="fade-in-repeat" 
    ng-repeat="transaction in transactions track by transaction ._id">