中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

AngularJS雙向數據綁定原理之$watch、$apply和$digest怎么用

發布時間:2021-08-23 09:58:23 來源:億速云 閱讀:107 作者:小新 欄目:web開發

小編給大家分享一下AngularJS雙向數據綁定原理之$watch、$apply和$digest怎么用,希望大家閱讀完這篇文章之后都有所收獲,下面讓我們一起去探討吧!

背景

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.js

app.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 執行的流程是:

  1. 在瀏覽器按下按鈕;

  2. 瀏覽器接收到一個事件,進入angular context。

  3. $digest循環開始執行,查詢每個$watch是否變化。

  4. 由于監視$scope.name的$watch報告了變化,它會強制再執行一次$digest循環。

  5. 新的$digest循環沒有檢測到變化,此時瀏覽器拿回控制權,更新與$scope.name新值相應部分的DOM。

從中可以看出AngularJS的一個明顯的不足:每一個進入angular context的事件都會執行一個$digest循環,哪怕僅僅是輸入一個字母,$digest 都會遍歷整個頁面的所有$watch。

$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> 
 <div ng-controller="MainCtrl" >
  <input ng-model="name" />
  Name updated: {{updated}} times.
 </div> 
 <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 的值隨之變化,而且能顯示變化的次數。

AngularJS雙向數據綁定原理之$watch、$apply和$digest怎么用

$watch 檢測到的數據變化

看完了這篇文章,相信你對“AngularJS雙向數據綁定原理之$watch、$apply和$digest怎么用”有了一定的了解,如果想了解更多相關知識,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

华容县| 凉山| 恩施市| 独山县| 商洛市| 类乌齐县| 英山县| 辰溪县| 重庆市| 天祝| 综艺| 富源县| 包头市| 牟定县| 邹平县| 噶尔县| 南宫市| 南丰县| 开江县| 贡觉县| 达日县| 土默特左旗| 凌云县| 阿克苏市| 会昌县| 陆丰市| 西宁市| 且末县| 麦盖提县| 家居| 江口县| 北流市| 天长市| 体育| 田林县| 太湖县| 同德县| 陆川县| 张北县| 福海县| 双鸭山市|