2014-09-19 16 views
5

Tôi đã có một ứng dụng góc như:Tại sao chức năng ng-style được áp dụng hai lần?

angular.module('ngStyleApp', []) 

.controller('testCtrl', function($scope) { 
    $scope.list = [1,2,3]; 
    $scope.getStyles = function(index) { 
     console.log('getting styles for index ' + index); 
     return { 
      color: 'red' 
     }; 
    }; 
}); 

với đánh dấu tương ứng:

<div ng-app="ngStyleApp"> 
    <ul ng-controller="testCtrl"> 
     <li ng-repeat="value in list" ng-style="getStyles($index)"> 
      {{value}} 
     </li> 
    </ul> 
</div> 

Kết quả có thể nhìn thấy là ba mục danh sách đỏ, như mong đợi. Nhưng câu lệnh được ghi vào bảng điều khiển tổng cộng 6 lần, ngụ ý rằng chế độ xem được hiển thị hai lần:

getting styles for index 0 
getting styles for index 1 
getting styles for index 2 
getting styles for index 0 
getting styles for index 1 
getting styles for index 2 

Tại sao?

Trả lời

6

Các kiễu góc $digest chu kỳ đánh giá các thuộc tính ngStyle ít nhất hai lần - một lần để có được giá trị và một lần để kiểm tra xem nó đã thay đổi. Nó thực sự tiếp tục lặp lại cho đến khi giá trị được giải quyết để có khả năng kiểm tra giá trị nhiều lần.

Dưới đây là một hình ảnh để minh họa điều này:

enter image description here

Dưới đây là một bài đăng blog tốt minh họa này: angular digest blog

Trên thực tế, cố gắng trích dẫn này từ StackOverflow nói rằng nó rất tốt:

Khi chức năng đã xem được đánh giá (trong $ digest) nếu bất kỳ chức năng nào trong số chúng đã thay đổi từ p revious $ digest sau đó Angular biết rằng thay đổi có thể gợn qua các chức năng đã xem khác (có lẽ biến được thay đổi được sử dụng trong một hàm được theo dõi khác). Vì vậy, mỗi chiếc đồng hồ được đánh giá lại (còn được gọi là xử lý bẩn) cho đến khi không có đồng hồ nào dẫn đến thay đổi. Vì vậy, thông thường bạn sẽ thấy 2 cuộc gọi đến các chức năng theo dõi mỗi lần thông báo và đôi khi nhiều hơn (tối đa 10 đến 10 vòng lặp thông qua tính năng này và báo cáo lỗi nói rằng nó không thể ổn định).

(Reference here)

+0

Sau đó, tại sao lệnh ng-init đó chỉ được gọi một lần? – Josep

+1

ng-init thực hiện điều đó - nó được sử dụng để thiết lập một giá trị một lần để khởi tạo chỉ thị –

+0

Đó là vì ng-init không cần phải đánh giá lại, nó không đăng ký bất kỳ đồng hồ nào. – PSL

1

Đây là mã của chỉ thị ngStyle:

var ngStyleDirective = ngDirective(function(scope, element, attr) { 
    scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) { 
    if (oldStyles && (newStyles !== oldStyles)) { 
     forEach(oldStyles, function(val, style) { element.css(style, '');}); 
    } 
    if (newStyles) element.css(newStyles); 
    }, true); 
}); 

Chú ý rằng có một scope.$watch cho attr.ngStyle, rằng đồng hồ là những gì làm cho nó kích hoạt hai lần.

Ví dụ: nếu bạn cố gắng làm điều tương tự bằng cách sử dụng ngInit, bạn sẽ nhận thấy rằng hàm chỉ được gọi một lần. Bây giờ, cho phép có một cái nhìn vào mã của chỉ thị ngInit, nó trông như thế này:

var ngInitDirective = ngDirective({ 
    priority: 450, 
    compile: function() { 
    return { 
     pre: function(scope, element, attrs) { 
     scope.$eval(attrs.ngInit); 
     } 
    }; 
    } 
}); 

Chú ý rằng không có watch trong chỉ thị này.

Các vấn đề liên quan