【问题标题】:AngularJS Checkbox Rendering Very Slow the First TimeAngularJS 复选框第一次渲染非常慢
【发布时间】:2017-09-05 20:35:36
【问题描述】:

我遇到了运行 Angular 1.5.9 的旧版应用程序的问题。控制器包含以下循环,该循环由页面上的“全选”链接触发:

                var len = $scope.payments.length, i;
                for (i = 0; i < len; i++) {
                    $scope.payments[i].selected = true;
                }

支付数组中对象中的 selected 属性绑定到视图中的复选框:

<tr data-ng-repeat="payment in payments | orderBy: 'payDate'">
    <td><input type="checkbox" data-ng-model="payment.selected" data-ng-change="setSelectedTotal()"/>...

表格中的数组/行中最多有 15000 个项目,在页面加载后第一次单击“全选”链接时,在选中所有复选框的情况下刷新视图最多需要 40 秒。如果我清除复选框,然后再次单击全选链接,复选框会在大约 1 秒或更短的时间内显示为选中状态。在所有后续单击“全选”链接时都是如此——它只是第一次很慢,但之后每次都需要一秒钟或更短的时间。我怀疑这与模型绑定有关,因为当我用 console.time() 和 console.timeEnd() 包围循环时,即使第一次尝试,循环也只需要几毫秒。所以问题在于循环完成后发生的事情。我尝试从 ng-model 切换到 ng-checked 只是为了看看它是否会加快速度,但它给了我一个错误,实际上该应用程序取决于绑定到所选属性的复选框。我还尝试在页面加载的前一千个复选框上运行全选(然后是全部清除),但这没有任何区别。任何关于第一次为什么这么慢和/或如何加快速度的见解将不胜感激。

【问题讨论】:

  • 通过 $index 进行跟踪是否会提高性能?
  • 如果你删除 orderBy 会有明显的不同吗?
  • 顺便说一句,看看您是否可以使用简化模型的 plunker 重现它会很好,它还可以帮助其他人看到问题并修复。
  • 致@ABOS 评论.. 在将项目绑定到范围之前尝试对其进行排序。您还可以尝试一种分页策略,将实际数组的一个子集支付给它,并使用一个按钮(下一页)来选择下一个支付子集。
  • 我猜缓慢是由于 Angular 第一次实际渲染 dom,但后来,它只是更新它

标签: javascript angularjs checkbox


【解决方案1】:

这是一个进行了一些优化的示例。

注意:我使用 document.querySelectorAll 在控制器外部选择/取消选择,因为它比依赖 $scope 数据快得多。

angular.module('app', []);

angular.module('app')
    .controller('ExampleController', ['$scope', function($scope) {

        $scope.payments = [];
        $scope.selected = false;
        $scope.total = 0;
        $scope.itemsCount = 7500;

        // Populate with 
        populate($scope.itemsCount);

        $scope.updateTotal = function() {
            let total = 0;
            for (let i = 0; i < $scope.payments.length; i++) {
                if ($scope.payments[i].selected === true) {
                    total += $scope.payments[i].amount;
                }
            }
            $scope.total = total;
        }

        $scope.toggleAll = function() {
            // Toggle global selected state
            $scope.selected = !$scope.selected;
            for (let i = 0; i < $scope.payments.length; i++) {
                $scope.payments[i].selected = $scope.selected;
            }
            $scope.updateTotal();
        }

        $scope.toggle = function(index) {
            $scope.payments[index].selected = !$scope.payments[index].selected;
            $scope.updateTotal();
        }

        function populate(count) {
            for (let i = 0; i < count; i++) {
                $scope.payments.push({
                    amount: i,
                    selected: false
                });
            }
        }

    }]);


// Toggle all checkbox

function vanillaToggleAll(event) {
    var el = event.srcElement || event.target;
    var checkboxes = document.querySelectorAll("input[type='checkbox']");
    for (let i = 0; i < checkboxes.length; i++) {
        checkboxes[i].checked = el.checked;
    }
}
<!doctype html>

<html lang="en" ng-app="app">
<head>
  <meta charset="utf-8">
  <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.4/angular.min.js"></script>
  <script src="script.js"></script>
</head>
 
<body ng-controller="ExampleController">

<h1>Items: {{itemsCount}}, Total: {{total}} USD</h1>

<table>
	<thead>
	  <tr>
  		<td>
  			<input type="checkbox" ng-click="toggleAll()" onclick="vanillaToggleAll(event)">
  			<label>Select/Unselect All</label>
  		</td>
	  </tr>
	</thead>
	<tbody>
		<tr ng-repeat="payment in payments | orderBy: 'amount'">
	    	<td>
	    		<input type="checkbox" class="checkbox" ng-bind="payment.selected" ng-click="toggle($index)" />
	    		<label ng-bind="::payment.amount"></label> USD
	    	</td>
	    </tr>
	</tbody>    
</table>    
</body>
</html>

A demo plunker7500 个可玩的物品

以下是结果,我使用 Chrome 分析器来分析加载、编写脚本、渲染所花费的时间...

1000 项

10000 项

15000 项

【讨论】:

  • 代码清理:我已经从控制器中删除了选择/取消选择复选框的代码,因为它不能操纵 DOM,而只能操纵 $scope 值。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-06-06
  • 1970-01-01
  • 2015-08-06
  • 2018-06-20
  • 1970-01-01
  • 2014-02-15
  • 2013-07-08
相关资源
最近更新 更多