$scope.apply trong AngularJS
Nếu như bạn đã viết một khối lượng lớn code AngularJS thì bạn hẳn phải biết về một scope hay sử dụng là $scope.apply(), theo như giới thiệu thí nó là một phương pháp dùng để cập nhật các bindings nhưng tại sao nó tồn tại và khi nào được sử dụng? và hôm nay chúng ta sẽ nghiên cứu kỹ khi nào thì sử ...
Nếu như bạn đã viết một khối lượng lớn code AngularJS thì bạn hẳn phải biết về một scope hay sử dụng là $scope.apply(), theo như giới thiệu thí nó là một phương pháp dùng để cập nhật các bindings nhưng tại sao nó tồn tại và khi nào được sử dụng? và hôm nay chúng ta sẽ nghiên cứu kỹ khi nào thì sử dụng $scope.apply và những tác dụng của nó trong AngularJS.
Để hiểu rõ khi nào thì sử dụng $scope.apply() chúng ta hay trở về với những điều cơ bản của JavaScript.
Chúng ta hẳn biết những đoạn mã javaScript chúng ta đã viết không chạy một lần tất cả. thay vào đó là thực hiện lần lượt từng đoạn mã từ lúc bắt đầu đến lúc kết thúc và khi một đoạn mã đang chạy thì sẽ không gì xảy ta trên trình duyệt của chúng ta và khi đó giao diện của chúng ta hoàn toàn tĩnh.
Thay vào đó, chúng ta có một công việc mà khi thực hiện sẽ mất một khoảng thời gian, ví dụ như một đoạn ajax. Khi đợi sự kiện đang được thực thi hay thiết lập thời gian chờ đợi, chúng ta sẽ thiết lập một chức năng dùng để callback và kết thúc, sau khi yêu cầu ajax hoàn tất, sự kiện click đươc phát hiện hay thới gian chờ đợi kết thúc, một đoạn javascript được chạy và kết thúc.
Chúng ta có đoạn mã sau:
var button = document.getElementById('click-me'); function buttonClicked () { alert('the button was clicked'); } button.addEventListener('click', buttonClicked); function timerComplete () { alert('timer complete'); } setTimeout(timerComplete, 2000);
Khi mã code javascrip được load, nó sẽ tìm nút và add sự kiện khi nhấp chuột và thiết lập thời gian chờ.
Khi chung ta click vào nút #click-me thì trình duyệt sẽ thực thi hành động được thiết lập trong sự kiện click. và sau 2000ms trình duyệt sẽ thực thi sự kiện được thiết lập trong hàm timerComplete(). khi đó tất các các code javascrip chúng ta viết đã được chạy hoàn tất.
Nếu chúng ta dùng AngularJS để cập nhật data trong code Javascript vậy thì làm sao để AngularJS biết khi dữ liệu được cập nhật và trang cần được cập nhật hay không.
Có vài giải pháp cho vấn đề này, code cân được thiết lập khi giá trị thay đổi. Có hai cách chính để giải quyết:
-
Cách đầu tiên là dùng một đối tượng. đối tượng này không có thuộc tính và có nhiệm vụ lưu trữ giá trị được thiết lập trong phương thưc, khi đó các thay đổi được ghi nhân và trang sẽ được cập nhật. Nhưng với cách này, chúng ta phải sử dụng cấu trúc obj.set('key', 'value') để gắn giá trị.
-
AngularJS cho phép chúng ta sử dụng bất kì giá trị nào cho một biến liên kết. Trong phần cuối của đoạn mã javascript sẽ kiểm tra xem giá trị được tha đổi hay không. Cách này có lợi ích lơn nhất là chúng ta có thể sử dụng một đối tượng bình thương và cập nhât sẽ liệu mà chúng ta muốn. Đối với cách này, chúng ta cần phải biết khi dữ liệu được thay đổi và lúc này chúng ta cần dùng $scope.apply().
apply và digest
Hàm $digest() là một phương thức dùng được duyệt tất cả và thực thi tất cả các bộ theo dõi (watch) được khai báo trong Scope, cũng như của các scope con của nó. Bên trong các thành phần AngularJS, hàm `digest()` được gọi ở những chỗ AngularJS thấy cần thiết kích hoạt các bộ theo dõi để cập nhật thay đổi.
angular.module('myApp', []) .controller('test', function($scope) { setTimeout(function () { $scope.message = "Timeout called!"; // AngularJS unaware of update to $scope }, 2000); $scope.digest(); })
Tuy nhiên chúng ta thường không sử dụng hàm này mà dùng apply(), khi gọi apply() AngularJS sẽ tự động gọi đến digest() để cập nhật tất cả các bindings và watchers.
Vậy $scope.apply() sẽ được dùng ở vị trí trong code js của chúng ta? Trên thực tế AngularJS gọi gần như hầu hết các code với một lần gọi apply(). như các sự kiện click, khởi tạo controller, $$ttp... Vì vậy chúng ta chỉ cần gọi 1 lần apply(), trên thực tế nếu gọi apply() trong apply() sẽ gây ra lỗi.
Dưới đây là một ví dụ về việc sử dụng apply() trong AngularJS
<body ng-app="myApp"> <div ng-controller="test"> {{message}} </div> </body>
angular.module('myApp', []) .controller('test', function($scope) { $scope.message = "Waiting 2000ms for update"; setTimeout(function () { $scope.message = "Timeout called!"; // AngularJS unaware of update to $scope }, 2000); })
Demo: https://jsfiddle.net/huannd/2jcg0c7d/1/
Khi sử dụng Khi sử dụng apply() thì thông báo message của chúng ta sẽ thay đổi và trang được cập nhật.
angular.module('myApp', []) .controller('test', function($scope) { $scope.message = "Waiting 2000ms for update"; setTimeout(function () { $scope.$apply(function () { $scope.message = "Timeout called!"; }) // AngularJS unaware of update to $scope }, 2000); })
Demo: https://jsfiddle.net/huannd/8jso3xff/