[javascript] 數據綁定在AngularJS中如何工作?



Answers

Misko已經很好地描述了數據綁定的工作原理,但我想在數據綁定的性能問題上添加我的觀點。

正如米斯科所說,2000年左右的綁定就是你開始看到問題的地方,但是你不應該在頁面上有超過2000條信息。 這可能是事實,但並不是每個數據綁定對用戶都是可見的。 一旦你開始用雙向綁定構建任何類型的窗口小部件或數據網格,你就可以輕鬆地打2000個綁定,而不會產生不好的ux。

例如,考慮一個組合框,您可以在其中鍵入文本以過濾可用選項。 這種控制可能有150個項目,仍然是非常有用的。 如果它有一些額外的功能(例如當前選擇的選項上的特定類),則每個選項開始獲得3-5個綁定。 將其中三個小部件放在一個頁面上(例如,一個選擇一個國家,另一個選擇所在國家的一個城市,第三個選擇一個酒店),你已經在1000到2000之間的綁定。

或者考慮企業Web應用程序中的數據網格。 每頁50行不是不合理的,每行可能有10-20列。 如果你用ng-repeats構建這個,並且/或者在一些使用綁定的單元格中有信息,那麼你可能會單獨接近2000個綁定。

我發現這在使用AngularJS時是一個巨大的問題,目前唯一能夠找到的解決方案是構建小部件而不使用雙向綁定,而是使用ngOnce,註銷觀察者和類似的技巧,或構造指令它使用jQuery和DOM操作構建DOM。 我覺得這首先打破了使用Angular的目的。

我很樂意聽取其他處理方法的建議,但也許我應該寫下自己的問題。 我想在評論中提到這一點,但事實證明這樣做太長了......

TL; DR
數據綁定可能會導致複雜頁面上的性能問題。

Question

數據綁定在AngularJS框架中如何工作?

我沒有在他們的網站上找到技術細節。 當數據從視圖傳播到模型時,它如何工作或多或少都很清楚。 但是,AngularJS如何在沒有setter和getters的情況下跟踪模型屬性的變化?

我發現有JavaScript觀察者可以做這項工作。 但是它們在Internet Explorer 6Internet Explorer 7不受支持。 那麼,AngularJS如何知道我改變了以下內容並在視圖上反映了這種變化?

myobject.myproperty="new value";



用圖片解釋:

數據綁定需要映射

範圍中的引用不完全是模板中的引用。 當你數據綁定兩個對象時,你需要第三個接受第一個對象並修改其他對象。

在這裡,當你修改<input> ,你可以觸摸data-ref3 。 經典的數據綁定機制將改變data-ref4 。 那麼其他{{data}}表達式將如何移動?

事件導致$ digest()

Angular維護每個綁定的oldValuenewValue 。 在每個Angular事件之後 ,著名的$digest()循環將檢查WatchList以查看是否有更改。 這些Angular事件ng-clickng-change$http completed ...只要任何oldValuenewValue不同, $digest()就會循環。

在前面的圖片中,它會注意到data-ref1和data-ref2已經改變。

結論

這有點像雞蛋和雞肉。 你永遠不知道誰是首發的,但希望大部分時間都能按預期工作。

另一點是你可以很容易地理解內存和CPU的簡單綁定的影響。 希望台式機足夠處理這個問題。 手機並不那麼強大。




以下是使用輸入字段與AngularJS進行數據綁定的示例。 我會在稍後解釋

HTML代碼

<div ng-app="myApp" ng-controller="myCtrl" class="formInput">
     <input type="text" ng-model="watchInput" Placeholder="type something"/>
     <p>{{watchInput}}</p> 
</div>

AngularJS代碼

myApp = angular.module ("myApp", []);
myApp.controller("myCtrl", ["$scope", function($scope){
  //Your Controller code goes here
}]);

正如你在上面的例子中看到的, AngularJS使用ng-model來監聽並觀察HTML元素上發生了什麼,特別是在input字段上。 什麼時候發生,做點什麼。 在我們的例子中, ng-model綁定到我們的視圖,使用鬍子符號{{}} 。 無論輸入字段內輸入什麼,都會立即顯示在屏幕上。 這就是數據綁定的美妙之處,以最簡單的形式使用AngularJS。

希望這可以幫助。

Codepen看到一個可用的例子




這是我的基本理解。 這可能是錯的!

  1. 通過傳遞函數(將要觀看的事物返回)到$watch方法來$watch
  2. 監視項目的更改必須在由$apply方法包裝的代碼塊內進行。
  3. $apply結束時,會調用$digest方法,它會檢查每個手錶並檢查自上次運行$digest以來是否發生了更改。
  4. 如果發現任何更改,則摘要將被再次調用,直到所有更改穩定為止。

在正常的開發中,HTML中的數據綁定語法告訴AngularJS編譯器為您創建手錶,並且控制器方法在$apply已經運行。 所以對於應用程序開發者來說,它是全透明的




AngularJS通過三個強大的函數: $watch()$digest()$apply()來處理數據綁定機制。 大多數情況下,AngularJS會調用$ scope。$ watch()和$ scope。$ digest(),但在某些情況下,您可能需要手動調用這些函數以使用新值進行更新。

$ watch() : -

該函數用於觀察$ scope中變量的變化。 它接受三個參數:表達式,偵聽器和相等對象,其中偵聽器和相等對像是可選參數。

$ digest() -

此函數遍歷$ scope對像中的所有監視及其子$ scope對象
(如果有的話)。 當$ digest()遍歷手錶時,它會檢查表達式的值是否已經改變。 如果值已更改,AngularJS將使用新值和舊值調用監聽器。 每當AngularJS認為有必要的時候,都會調用$ digest()函數。 例如,點擊按鈕後,或在AJAX調用之後。 您可能會遇到一些AngularJS不會為您調用$ digest()函數的情況。 在這種情況下,你必須自己調用它。

$ apply() -

Angular會自動更新僅在AngularJS環境中的模型更改。 當你在Angular上下文以外的任何模型中進行更改(如瀏覽器DOM事件,setTimeout,XHR或第三方庫)時,則需要手動調用$ apply()來通知Angular。 當$ apply()函數調用完成時,AngularJS會在內部調用$ digest(),以便更新所有數據綁定。




  1. 單向數據綁定是一種從數據模型中獲取值並插入到HTML元素中的方法。 沒有辦法從視圖更新模型。 它用於傳統的模板系統。 這些系統只能在一個方向上綁定數據。

  2. Angular應用程序中的數據綁定是模型和視圖組件之間數據的自動同步。

數據綁定使您可以將模型視為應用程序中的單一來源。 該視圖始終是該模型的投影。 如果模型發生變化,視圖會反映變化,反之亦然。




Related