淘汰foreach vs Angular ng-repeat

时间:2014-01-10 18:12:49

标签: angularjs

我使用Knockout做了什么,我正在尝试使用Angular。

在我当前的项目中,我有一个表,通过scroll事件添加数据。当用户向下滚动时,我在表的末尾添加了20行,总行数可以达到2k-10k。我开始显示20条记录,当用户向下滚动时,我会继续添加20行,直到达到总行数。

正如在我的Angular小提琴示例中,当使用重复时,如果将新数据推送到数组'' Angular"执行所有记录并再次渲染它们但是敲除只是执行并呈现新添加的记录。在我的项目中,因为我在一个表中显示数千个数据,这种角度有效,或者我认为它的工作方式会影响我的表现。

仅仅几个星期,我使用角度我不知道如果我做错了什么或者我需要修改一些东西。

Knockoutjs Example

<h2>Your seat reservations</h2>

<table>
    <thead><tr>
        <th>Passenger name</th><th>Meal</th><th>Test</th>
    </tr></thead>
    <tbody data-bind="foreach: seats()">
        <tr>
           <td data-bind="text: mealName"></td>
           <td data-bind="text: price"></td>
           <td data-bind="text: $root.cellAdded()"></td>
        </tr>    
    </tbody>
</table>
<button data-bind="click: $root.PushData()">I am Here</button>

JS:

// Overall viewmodel for this screen, along with initial state
function ReservationsViewModel() {
   var self = this;

   self.cellAdded = function(){
        console.log('Test Added');
        return 'ok';
    };

    self.PushData = function(){
        console.log('PushData Called');
        self.seats.push({ mealName: "Standard (sandwich)", price: 0 });
    };


    // Editable data
    self.seats = ko.observableArray([
       { mealName: "Standard (sandwich)", price: 0 },
        { mealName: "Premium (lobster)", price: 34.95 },
        { mealName: "Ultimate (whole zebra)", price: 290 }
    ]);
}

ko.applyBindings(new ReservationsViewModel());

AngularJS Example

<div ng-app>

<div ng-controller="TodoCtrl">
<h2>Your seat reservations</h2>

<table>
    <thead><tr>
        <th>Passenger name</th><th>Meal</th><th>Test</th>
    </tr></thead>
    <tbody >
        <tr ng-repeat="seat in seats">
           <td>{{seat.mealName}}</td>
           <td>{{seat.price}}</td>
           <td>{{callMe()}}</td>
        </tr>    
    </tbody>
</table>
<button ng-click="addRow()">Add Row</button>

</div>
    </div>

JS:

function TodoCtrl($scope) {

    $scope.callMe = function(){
        console.log('Test Added');
        return 'Yes';
    };
    // initialize controller's model    
   $scope.seats = [
       { mealName: "Standard (sandwich)", price: 0 },
        { mealName: "Premium (lobster)", price: 34.95 },
        { mealName: "Ultimate (whole zebra)", price: 290 }
    ];

    // Define member functions
    $scope.addRow = function() {
        console.log('PushData Called');
        $scope.seats.push( { mealName: "Standard (sandwich)", price: 0 });

    };

}

1 个答案:

答案 0 :(得分:1)

我建议更新到Angular 1.3+并使用其一次性绑定功能,因为记录在添加后不会更改。这样可以最大限度地减少DOM上的手表数量,并有助于提高性能。

<div ng-app>

  <div ng-controller="TodoCtrl">
    <h2>Your seat reservations</h2>

    <table>
      <thead><tr>
        <th>Passenger name</th><th>Meal</th><th>Test</th>
      </tr></thead>
      <tbody >
        <tr ng-repeat="seat in seats">
          <td>{{::seat.mealName}}</td>
          <td>{{::seat.price}}</td>
          <!--<td>{{callMe()}}</td>-->
        </tr>    
      </tbody>
   </table>
   <button ng-click="addRow()">Add Row</button>
  </div>
</div>

另外,我建议在表达式中删除该函数调用,因为每次Angular运行摘要周期时都会对其进行评估,这是一个真正的性能杀手。

如果您想检查您的模型是否已更新,请在控制器中使用$ watch(https://docs.angularjs.org/api/ng/type/ $ rootScope.Scope)。

$scope.$watch('seats', function() {
   console.log('Test Added');
});

另一个与性能无关的提示:这是一种很好的做法,有助于最大限度地减少范围问题,以便始终在控制器中使用某种模型对象。所以你的控制器看起来像这样:

function TodoCtrl($scope) {

  // initialize controller's model
  $scope.model = {};
  $scope.model.seats = [
     { mealName: "Standard (sandwich)", price: 0 },
     { mealName: "Premium (lobster)", price: 34.95 },
     { mealName: "Ultimate (whole zebra)", price: 290 }
  ];

  // Define member functions
  $scope.addRow = function() {
    console.log('PushData Called');
    $scope.model.seats.push( { mealName: "Standard (sandwich)", price: 0 });
  };

  $scope.$watch('model.seats', function() {
    console.log('Test Added');
  });
}

和您的HTML一样:

<div ng-app>

  <div ng-controller="TodoCtrl">
    <h2>Your seat reservations</h2>

    <table>
      <thead><tr>
        <th>Passenger name</th><th>Meal</th><th>Test</th>
      </tr></thead>
      <tbody >
        <tr ng-repeat="seat in model.seats">
          <td>{{::seat.mealName}}</td>
          <td>{{::seat.price}}</td>
          <!--<td>{{callMe()}}</td>-->
        </tr>    
      </tbody>
   </table>
   <button ng-click="addRow()">Add Row</button>
  </div>
</div>

此外,正如@Gabe已经提到的,ngInfiniteScroll可能是您用例的一个很好的补充:http://binarymuse.github.io/ngInfiniteScroll/