2015-05-24 19 views
8

AngularJS cho phép bạn thực hiện liên kết dữ liệu hai chiều. Tuy nhiên, phần thú vị là làm thế nào nó phát hiện thay đổi mô hình? Mô hình thường là một đối tượng đơn giản như mã bên dưới. Chúng ta có thể thay đổi thuộc tính name của $scope.user nhưng AngularJS phát hiện ra mô hình đã thay đổi như thế nào? Có AngularJS enum tất cả các thuộc tính của đối tượng $scope?AngularJS triển khai cơ chế ràng buộc dữ liệu hai chiều của nó như thế nào?

angular.module('myApp', []) 
     .controller('BusinessCardController', function($scope){ 
     $scope.user = { 
      name: 'Tanay Pant' 
     } 
     }); 

<input type="text" ng-model="user.name" placeholder="Full Name" /> 

Trả lời

10

Có chu kỳ phân hủy, trong đó phạm vi kiểm tra tất cả biểu thức $ xem và so sánh chúng với giá trị trước đó. Nó nhìn vào các mô hình đối tượng cho các thay đổi, nếu giá trị cũ không giống như giá trị mới, AngularJS sẽ cập nhật các vị trí thích hợp, kiểm tra bẩn.

Để chu kỳ phân hủy được thực hiện $apply(fn) phải được chạy, đây là cách bạn nhập thế giới Góc từ JavaScript. Cách gọi số $apply(fn) được gọi (lấy từ AngularJs integration with browser):

  1. Vòng lặp sự kiện của trình duyệt chờ một sự kiện đến. Sự kiện là tương tác của người dùng, sự kiện hẹn giờ hoặc sự kiện mạng (phản hồi từ máy chủ).
  2. Gọi lại của sự kiện được thực hiện. Điều này đi vào ngữ cảnh JavaScript. Gọi lại có thể sửa đổi cấu trúc DOM.
  3. Sau khi gọi lại thực thi, trình duyệt rời khỏi ngữ cảnh JavaScript và hiển thị lại chế độ xem dựa trên các thay đổi DOM.

Data Binding

Digest Cycle Explanation

Để đạt được hai chiều ràng buộc, chỉ đăng ký theo dõi. Để trang nhanh và hiệu quả, chúng tôi cần thử và giảm tất cả những người theo dõi mà chúng tôi tạo ra. Vì vậy, bạn nên cẩn thận khi sử dụng liên kết hai chiều - tức là chỉ sử dụng nó khi bạn thực sự cần thiết. Nếu không sử dụng một chiều:

<h1> {{ ::vm.title }} </h1>

Ở đây nó là khá rõ ràng rằng tiêu đề của trang có lẽ sẽ không thay đổi trong khi người dùng trên trang - hoặc cần nhìn thấy chiếc mới nếu nó là đã thay đổi. Vì vậy, chúng tôi có thể sử dụng :: để đăng ký liên kết một chiều trong giai đoạn liên kết mẫu.

Các vấn đề chính mà tôi đã thấy với các vụ nổ người xem là lưới với hàng trăm hàng. Nếu những hàng này có một vài cột và trong mỗi ô có ràng buộc dữ liệu hai chiều, thì bạn đang ở trong một điều trị. Bạn có thể ngồi lại và chờ đợi như trong thời gian modem cho trang để tải!

7

Ràng buộc hai chiều bị giới hạn hầu như chỉ dành cho các thành phần sử dụng ng-model. Hướng đi từ chế độ xem đến mô hình sử dụng trình xử lý sự kiện chuẩn để phát hiện các thay đổi phải được cập nhật trong mô hình (ví dụ: onchange). Hướng đi từ mô hình trở lại chế độ xem được cập nhật trong một $digest. Nhưng chúng tôi không gọi trực tiếp số $digest.

Mọi phần tử trên trang của bạn sẽ phản hồi chu kỳ thông báo, ở đâu đó, đính kèm người nghe và biểu thức vào phạm vi sử dụng $watch. Khi bạn viết {{ foo() }} hoặc khi bạn sử dụng ng-model='user.name', nội bộ có lời gọi đến số $watch được thực hiện nhân danh bạn với một biểu thức Javascript sẽ được chạy mỗi khi chu trình tiêu hóa được chạy.Việc đăng ký này có thể xảy ra trong quá trình biên dịch mẫu (ví dụ đầu tiên của chúng tôi), hoặc nó có thể xảy ra trong giai đoạn liên kết của một chỉ thị (thứ hai của chúng tôi).

Không có phép thuật nào ở đây. Các trình nghe được đính kèm là các hàm bình thường - trong ví dụ của chúng tôi, trình nghe cho biểu thức foo() được cung cấp cho bạn và nó sẽ cập nhật văn bản html trên trang, trong khi trình nghe cho biểu thức user.name sẽ gọi setText hoặc setOption, hoặc bất cứ điều gì được yêu cầu bởi đầu vào cụ thể mà ng-model đã được đính kèm.

Trong khi góc cạnh có thể xử lý hầu hết việc nghe, bạn có thể đính kèm biểu thức đồng hồ của riêng mình với người nghe của mình theo cách thủ công bên trong bất kỳ chức năng nào có quyền truy cập vào phạm vi (phạm vi quan trọng vì chúng tôi sẽ chia nhỏ những người xem đó trang bị xóa). Hãy chú ý vượt quá. Bindings không miễn phí, và nhiều thứ bị ràng buộc, trang sẽ trả lời càng chậm. Liên kết một lần là một cách để giảm chi phí này. Sử dụng $on với $emit$broadcast là loại khác.

Vậy khi nào thông báo được gọi? Nó chắc chắn không phải là tự động. Nếu chu trình tiêu hóa đang chạy, điều đó có nghĩa là ai đó ở đâu đó được gọi là $apply trên phạm vi của họ hoặc trên phạm vi gốc. ng-model gắn các trình xử lý sẽ phản hồi các sự kiện html thông thường và sẽ thực hiện cuộc gọi tới số $apply thay cho bạn. Nhưng foo(), mặt khác, sẽ không bao giờ được gọi cho đến khi một số đoạn mã khác ở đâu đó gọi $apply. May mắn thay, hầu hết các chức năng mà bạn điền vào để quấn các chức năng đó với một cuộc gọi đến $apply, vì vậy bạn không phải tự gọi điện thoại (ví dụ: $timeout được gói với $apply, đó là lý do chúng tôi sử dụng nó thay vì setTimeout) . Nhưng nếu bạn đang sử dụng thứ gì đó bên ngoài phạm vi góc (thư viện của bên thứ ba kết nối với các sự kiện), bạn cần nhớ tự gọi số $apply và giống như trên, bạn có thể thực hiện việc này theo cách thủ công bằng cách gọi $apply ở bất cứ nơi nào bạn có quyền truy cập đến một phạm vi.

1

Để làm cho Ràng buộc dữ liệu có thể, AngularJS sử dụng $ watch API để quan sát các thay đổi trên phạm vi. AngularJS đăng ký người theo dõi cho mỗi biến trên phạm vi để quan sát giá trị trong đó. Nếu giá trị của biến trên phạm vi nhận được thay đổi, thì chế độ xem được cập nhật tự động.

Điều đó xảy ra do chu kỳ $ digest được kích hoạt. Do đó, AngularJS xử lý tất cả những người theo dõi đã đăng ký trên phạm vi hiện tại và trẻ em và kiểm tra các bản cập nhật và gọi cho người nghe chuyên dụng cho đến khi mô hình được ổn định và không có người nghe nào bị sa thải. Khi vòng lặp $ digest kết thúc quá trình thực hiện, trình duyệt sẽ hiển thị lại DOM và phản ánh các thay đổi

Theo mặc định, mọi biến trên phạm vi được quan sát theo góc. Bằng cách này, biến không cần thiết cũng được quan sát bởi góc cạnh mất thời gian và trang kết quả đang trở nên chậm.

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