AngularJS雙向資料綁定原理(詳細教學)
這篇文章主要介紹了AngularJS雙向資料綁定原理之$watch、$apply和$digest的應用,具有一定的參考價值,有興趣的小夥伴們可以參考一下
引子
這篇文章是寫給AngularJS新手的,如果你已經對AngularJS的雙向資料綁定有了深入的了解,直接去閱讀原始碼好了。
背景
AngularJS開發者都想知道雙向資料綁定是怎麼實現的。與data-binding相關的術語琳瑯滿目: $watch,$apply,$digest,dirty-checking等等它們是如何運作的呢?讓我們從頭開始講起吧
AngularJS 的雙向資料綁定是被瀏覽器逼的
瀏覽器看上去很美,其實在資料互動這塊兒,由於瀏覽器的“不作為”,導致瀏覽器的資料刷新成為一個難題。具體來說,瀏覽器可以輕鬆監聽一個事件,例如:使用者點擊一個按鈕,或是在輸入框裡輸入東西,為此還提供了事件回調函數的API,事件的回調函數就會在javascript解釋器裡執行;但反過來就沒這麼簡單了,如果來自後台的數據發生了變化,需要通知給瀏覽器,讓瀏覽器刷新,瀏覽器並沒有提供這樣的數據交互機制,對於開發者來說,這是一個難以克服的障礙,該怎麼辦呢? AngularJS出現了,它透過$scope 很好地實現了雙向資料綁定,背後的原理就是$watch,$apply,$digest,dirty-checking
##$watch 佇列($watch list)
從字面上看,watch 是觀察的意思。每次將東西綁定到瀏覽器時,就會往$watch佇列插入一張$watch。想像一下$watch就是那個可以偵測它監視的model裡時候有變化的東西。例如你有如下的程式碼User: <input type="text" ng-model="user" /> Password: <input type="password" ng-model="pass" />這裡有個$scope.user,它被綁定在了第一個輸入框上,還有個$scope.pass,它被綁定在了第二個輸入框上;然後在$watch list裡面加入兩個$watch:建立一個controllers.js 文件,程式碼如下:
app.controller('MainCtrl', function($scope) { $scope.foo = "Foo"; $scope.world = "World"; });對應的html 檔案, index.html 程式碼如下:
Hello, {{ World }}這裡,即使在$scope上添加了兩個東西,但是只有一個綁定在了UI上,因此只生成了一個$watch. 再看下面的例子:controllers.js
app.controller('MainCtrl', function($scope) { $scope.people = [...]; });對應的html檔index.html
<ul> <li ng-repeat="person in people"> {{person.name}} - {{person.age}} </li> </ul>#這樣看來,又產生了多個$watch。每個person有兩個(一個name,一個age),然後ng-repeat是一個循環,因此10個person一共是(2 * 10) 1,也就是說有21個$watch。因此,每一個綁定到了瀏覽器上的資料都會產生一個$watch。對,那這寫$watch是什麼時候產生的呢?先回顧下AngularJS的載入原理
AngularJS的載入原理:
AngularJS的範本載入分為編譯(compile)和連結(linking)兩個階段,在linking階段,AngularJS解譯器會尋找每個directive,然後產生每個需要的$watch。對了,$watch就是在這個階段生成的。 接下來,開始用到$digest了$digest 循環
從字面上看,digest是「消化」的意思,總感覺這個名字怪怪的,跟不可思議的是dirty-checking, 字面意思“髒檢查”,還是不翻譯為好。原作者的本意絕對不是這個意思,只可意會不可言傳! $digest 是一個循環,它在循環做什麼呢? $digest 在遍歷我們的$watch。 $digest 一個個問$watch —— 「嗨,你觀察的資料改變了沒?」這個遍歷就是所謂的dirty-checking。既然所有的$watch都檢查完了,那就要問了:有沒有$watch更新過?如果有至少一個更新過,這個循環就會再次觸發,直到所有的$watch都沒有變化。這樣就能夠保證每個model都已經不會再改變。記住如果循環超過10次的話,它將會拋出一個異常,以免出現無限循環。當$digest循環結束時,DOM會相應地變化。 看段程式碼,例如: controllers.jsapp.controller('MainCtrl', function() { $scope.name = "Foo"; $scope.changeFoo = function() { $scope.name = "Bar"; } });對應的html文件,index.html
{{ name }} <button ng-click="changeFoo()">Change the name</button>這裡只有一個$watch,因為ng-click不產生$ watch(函數是不會變的)。 $digest 執行的流程是:
- 在瀏覽器按下按鈕;
- 瀏覽器接收到一個事件,進入angular context。
- $digest循環開始執行,查詢每個$watch是否有變化。
- 由於監視$scope.name的$watch報告了變化,它會強制再執行一次$digest循環。
- 新的$digest循環沒有偵測到變化,此時瀏覽器拿回控制權,更新與$scope.name新值對應部分的DOM。
$apply 的應用程式
Angular context 是整个Angular的上下文,也可以把它理解为Angular容器,那么,是谁来决定哪些事件可以进入 Angular Context,哪些事件又不能进入呢? 其控制器在 $apply手上。
如果当事件触发时,调用$apply,它会进入angular context,如果没有调用就不会进入。你可能会问:刚才的例子并没有调用$apply,这是怎么回事呢?原来,是Angular背后替你做了。当点击带有ng-click的元素时,事件就会被封装到一个$apply调用中。如果有一个ng-model="foo"的输入框,当输入一个字母 f 时,事件就会这样调用,$apply("foo = 'f';")。
$apply的应用场景
$apply是$scope的一个函数,调用它会强制一次$digest循环。如果当前正在执行$apply循环,则会抛出一个异常。
如果浏览器上数据没有及时刷新,可以通过调用$scope.$apply() 方法,强行刷新一遍。
通过 $watch 监控自己的$scope
<!DOCTYPE html> <html ng-app="demoApp"> <head> <title>test</title> <!-- Vendor libraries --> <script src="lib/jquery-v1.11.1.js"></script> <script src="lib/angular-v1.2.22.js"></script> <script src="lib/angular-route-v1.2.22.js"></script> </head> <body> <p ng-controller="MainCtrl" > <input ng-model="name" /> Name updated: {{updated}} times. </p> <script > var demoApp = angular.module('demoApp',[]); demoApp.controller('MainCtrl', function($scope) { $scope.name = "Angular"; $scope.updated = -1; $scope.$watch('name', function() { $scope.updated++; }); }); </script> </body> </html>
代码说明:
当controller 执行到 $watch时,它会立即调用一次,所以把updated的值设为 -1 。 上输入框中输入字符发生变化时,你会看到 updated 的值随之变化,而且能显示变化的次数。
$watch 检测到的数据变化
小结
我们对 AngularJS的双向数据绑定有了一个初步的认识,对于AngularJS来说,表面上看操作DOM很简单,其实背后有 $watch、$digest 、 $apply 三者在默默地起着作用。这个遍历检查数据是否发生变化的过程,称之为:dirty-checking。 当你了解了这个过程后,你会对它嗤之以鼻,感觉这种方法好low 哦。 确实,如果一个DOM中有 2000- 3000个 watch,页面的渲染速度将会大打折扣。
这个渲染的性能问题怎么解决呢?随着ECMAScript6的到来,Angular 2 通过Object.observe 极大地改善$digest循环的速度。或许,这就是为什么 Angular 团队迫不及待地推出 Angular 2 的原因吧。
上面是我整理给大家的,希望今后会对大家有帮助。
相关文章:
以上是AngularJS雙向資料綁定原理(詳細教學)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undress AI Tool
免費脫衣圖片

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

Javascript 是一個非常有個性的語言. 無論是從程式碼的組織, 還是程式碼的程式設計範式, 或物件導向理論都獨具一格. 而很早就在爭論的Javascript 是不是物件導向語言這個問題, 顯然已有答案. 但是, 即使Javascript 叱吒風雲二十年, 如果想要看懂jQuery, Angularjs, 甚至是React 等流行框架, 觀看《黑馬雲課堂JavaScript 高級框架設計視頻教程》就對了。

在現今資訊時代,網站已成為人們獲取資訊和交流的重要工具。一個響應式的網站能夠適應各種設備,為使用者提供優質的體驗,成為了現代網站開發的熱點。本篇文章將介紹如何使用PHP和AngularJS建立響應式網站,進而提供優質的使用者體驗。 PHP介紹PHP是一種開源的伺服器端程式語言,非常適合Web開發。 PHP具有許多優點,如易於學習、跨平台、豐富的工具庫、開發效

Vue元件通訊:使用$watch進行資料監聽在Vue開發中,元件通訊是常見的需求。 Vue提供了多種方式來實現元件之間的通信,其中一種常用的方式是使用$watch進行資料監聽。本文將介紹$watch的用法,並給出對應的程式碼範例。 Vue的實例物件提供了$watch方法,用於監聽資料的變化。 $watch接受兩個參數:要監聽的資料的屬性名,以及回呼函數。當監聽的數據

隨著網路的不斷發展,Web應用已成為企業資訊化建設的重要組成部分,也是現代化工作的必要手段。為了讓Web應用能夠方便開發、維護和擴展,開發人員需要選擇適合自己開發需求的技術框架和程式語言。 PHP和AngularJS是兩種非常流行的Web開發技術,它們分別是伺服器端和客戶端的解決方案,透過結合使用可以大大提高Web應用的開發效率和使用體驗。 PHP的優勢PHP

隨著Web技術的快速發展,單頁Web應用程式(SinglePageApplication,SPA)已成為越來越流行的Web應用程式模型。相較於傳統的多頁Web應用程序,SPA的最大優勢在於使用者感受更加流暢,同時伺服器端的運算壓力也大幅減少。在本文中,我們將介紹如何使用Flask和AngularJS來建構一個簡單的SPA。 Flask是一款輕量級的Py

隨著網路的普及和發展,前端開發已變得越來越重要。身為前端開發人員,我們需要了解並掌握各種開發工具和技術。其中,PHP和AngularJS是兩種非常有用且受歡迎的工具。在本文中,我們將介紹如何使用這兩種工具進行前端開發。一、PHP介紹PHP是一種流行的開源伺服器端腳本語言,它適用於Web開發,可以在Web伺服器和各種作業系統上運作。 PHP的優點是簡單、快速、便

隨著網路的普及,越來越多的人使用網路進行檔案傳輸和分享。然而,由於各種原因,使用傳統的FTP等方式進行檔案管理無法滿足現代使用者的需求。因此,建立一個易用、高效、安全的線上文件管理平台已成為了一種趨勢。本文介紹的線上文件管理平台,基於PHP和AngularJS,能夠方便地進行文件上傳、下載、編輯、刪除等操作,並且提供了一系列強大的功能,例如文件共享、搜尋、

這篇文章介紹的內容是關於AngularJS基礎入門介紹,有著一定的參考價值,現在分享給大家,有需要的朋友可以參考一下。
