1. 程式人生 > >【AngularJS】髒檢查機制及$timeout的妙用

【AngularJS】髒檢查機制及$timeout的妙用

||瀏覽器事件迴圈和Angular的MVW

        “髒檢查”是Angular中的核心機制之一,它是實現雙向繫結、MVVM模式的重要基礎。

        Angular將雙向繫結轉換為一堆watch表示式,然後遞迴檢查這些watch表示式的結果是否變了,如果變了,則執行相應的watcher函式。等到Model的值不再變化,也就不會再有watcher函式被觸發,一個完整的digest迴圈就結束了。

        因為我們不需要改變程式設計思維,就能用相同的語言、相同的事件模型,快速開發NodeJS程式,所以NodeJS迅速火起來,JavaScript full-stack也日漸流行。

        我們經常聽說Angular是一個MV*的框架,這是因為Angular拓展了瀏覽器的事件模型,建立了一個自己的上下文環境。

||Angular中的$watch函式

        watch表示式很靈活:可以是一個函式,可以是$scope上的一個屬性名,也可以是一個字串形式的表示式。$scope上的屬性名或表示式,最終仍會被$parse服務解析為響應的獲取屬性值的函式。

        所有的watcher函式都會被unshift函式插入scope.$$watchers陣列的頭部,以便後邊的$digest使用。

        最後,$watch函式會返回一個反註冊函式,一旦我們呼叫它,就可以移除剛才註冊的watcher。

        需要注意的是,Angular預設是不會使用angular.equals()函式進行深度比較的,因為使用===比較會更快,所以,它對陣列或者Object進行比較時檢查的是引用。這就導致內容完全相同的兩個表示式被判定為不同。如果需要進行深度比較,第三個可選引數objectEquality,需要顯式設定為true,如$watch('someExp', function(){...}, true)。

        Angular還提供了$watchGroup、$watchCollection方法來監聽陣列或者是一組屬性。

||Angular中的$digest函式

        前面提到Angular拓展了瀏覽器的事件迴圈,這是怎麼回事呢?

        當接受View上的事件指令所轉發的事件時,就會切換到Angular的上下文環境,來相應這類事件,$digest迴圈就會觸發。

        $digest迴圈實際上包括兩個while迴圈。它們分別是:處理$evalAsync的非同步運算佇列,處理$watch的watchers佇列。

        當$digest迴圈發生的時候,它會遍歷當前$scope及其所有子$scope上已註冊的所有watchers函式。

        遍歷一遍所有watcher函式稱為一輪髒檢查。執行完一輪髒檢查,如果任何一個watcher所監聽的值改變過,那麼就會重新再進行一輪髒檢查,直到所有的watcher函式都報告其所監聽的值不再變了。

        當$digest迴圈結束時,才把模型的變化結果更新到DOM中去。這樣可以合併多個更新,防止頻繁的DOM屬性。

        需要注意的是,在$digest迴圈結束之前,如果超過了10輪髒檢查,就會丟擲一個異常,以防止髒檢查無限迴圈下去。

        什麼時候會進入這個Angular的上下文環境,觸發“髒檢查機制”呢?這個問題很重要,它同時也是比較讓人頭疼的地方。

        每一個進入Angular上下文環境的事件,都會執行一次$digest迴圈。對於ngModel監聽的表單互動控制元件來說,每輸入一個字元,就會觸發一次迴圈來檢查$watcher函式,以便及時更新View。在Angular1.3之後可以利用ngModelOptions進行配置,來修改預設的觸發方式。

||Angular中的$apply

        $digest是一個內部函式,正常的應用程式碼中是不應該直接呼叫它的。要想主動觸發它,就要呼叫scope.$apply函式,它是觸發Angular“髒檢查機制”的常用公開介面。

        需要注意的是:Angular只能管理它所已知的行為觸發方式,而不能涵蓋所有的Angular操作場景。這就為什麼我們在封裝第三方jQuery外掛時,不能自動更新檢視,而需要我們手動呼叫$scope.$apply。

        整合jQuery外掛的時候,有時會出現digest in progress錯誤。如果排除Bug之後仍然不能解決,那麼可以考慮用$timeout來解決。

$timeout的妙用

        在延時任務中修改被繫結到介面中的變數,那麼window.setTimeout是不會觸發“髒檢查”來更新UI介面的。你可能想:加上$scope.$apply不就解決了嘛。是的,這能解決UI介面更新的問題,但是你可能會遇到另一個問題:

        Error: $digest already in progress

        這是怎麼回事兒?哦,Angular內部正在進行“髒檢查”。一位聰明的程式設計師巧妙地寫了下面一段程式碼來解決這個問題:

function safeApply(scope, fn){
    (scope.$$phase || scope.$root.$$phase) ? fn() : scope.$apply(fn);
}

        程式碼中,在執行apply函式之前會首先檢查Angular內部是不是正在做“髒檢查”,如果是就直接執行函式,不用$apply;反之沒有啟動髒檢查,那麼就$apply執行該函式。呵呵,“完美”解決,不是嗎?

        請注意,筆者在上面的完美兩個字上加了引號。Angular已經為我們內建了$timeout服務,它是Angular包裝原生JavaScript window.setTimeout而實現的。

        $timeout有很多妙用,但一定不要濫用,$timeout實現apply功能不應該是我們的第一方案,第一方案仍然應該是使用Angular內建的指令。

相關推薦

AngularJS檢查機制$timeout

||瀏覽器事件迴圈和Angular的MVW         “髒檢查”是Angular中的核心機制之一,它是實現雙向繫結、MVVM模式的重要基礎。         Angular將雙向繫結轉換為一堆w

Angularjs與Angular對檢查機制的理解

“髒檢查”是Angular中的核心機制之一,它是實現雙向資料繫結、MVVM模式的重要基礎。 AngularJS常用函式:$apply,$watch及$digest $digest是一個內部函式,正常的應用程式碼中是不應該直接呼叫它的。要想主動觸發它,就要呼叫scope.$

javajava反射機制,動態獲取對象的屬性和對應的參數值,並屬性按照字典序排序,Field.setAccessible()方法的說明可用於微信支付 簽名生成

modifier 直接 this 字段值 1-1 讓我 toupper ima play 方法1:通過get()方法獲取屬性值 package com.sxd.test.controller; public class FirstCa{ private

shopexapp開發機制

添加 dem ges http false .html return index array shopex的app開發機制詳解 shopex的app開發機制,讓我們可以實現以下特性: 1、建立自己的數據庫表。 2、創建自己的控制器。 3、在前後臺增加欄目

angularjs使用angular搭建PC端項目,開關按鈕

weight SM tps 資料 [] 文件 repeat amp title 方法一(使用指令) 1.指令(angular-ui-switch.js) angular.module(‘uiSwitch‘, []) app.directive(‘switch‘,

OS訊號量機制

儲存一下自己看,侵刪。 原文地址:http://blog.csdn.net/speedme/article/details/17597373 上篇部落格中(程序同步之臨界區域問題及Peterson演算法),我們對臨界區,臨界資源,鎖機制詳細解讀了下,留下了一個問題,就是鎖機制只能判斷臨界資源是否被佔用,所

AngularJs傳送Post請求

<!doctype html> <html lang="en"> <head> <!-- Required meta tags --> <meta charset="utf-8"> <meta name="viewport"

bug Waiting server-side response timeout.

問題一 在執行向solr匯入索引庫的過程中發生瞭如下錯誤 ERROR: [doc=536563] unknown field 'item_desc' 這是因為在solr的scheme.xml中沒有配置這個檔案的業務域,導致匯入失敗 解決方法: 在linux系統下進

angularJSService服務

AngularJS 中的服務是一個函式或物件。可以建立自己的服務,或使用內建服務。 內建服務 AngularJS 內建了30 多個服務。 1、  $location 服務,它可以返回當前頁面的 URL 地址。 var app = angular.module('myApp

資料篇Android混淆機制詳解學習資料

您將獲得以下內容: 通過 Gradle 編譯 Debug 和 Release 包的方式和介紹; 如何對程式碼進行混淆; Proguard 的特性介紹; Proguard 和 Dexguard 的區別;

說說zookeeper_工作機制和實現原理

本文簡單說說zookeeper的工作機制。 總體來說,客戶端先和zookeeper伺服器建立起一個TCP長連線(session),之後根據ACL許可權的設定,可在zookeeper伺服器上對目

122TensorFlow檢查地圖資料

下圖是加利福尼亞州的地圖: 為了驗證資料集是否存在缺陷,我們要讀取訓練集和驗證集,觀察這些資料的規律。並且按照經緯度繪製熱點圖,觀察地圖資料是否準確。 下面的程式碼完成了上面的工作: import tensorflow as tf import n

使用檢查機制實現資料的雙向繫結

1.實現效果: input標籤的值一變化,底下的p標籤的內容就跟著變化。 2.實現思路: 首先,angular得把我的舊資料記下來的吧。 angular的雙向繫結依賴髒檢查機制。為要雙向繫結的資料進行註冊,註冊到$scope上。($scope是a

專欄 - Android安全機制

Android安全機制 此專欄著重介紹Android安全機制相關知識,從Android系統安全的歷史和現狀,Android系統的幾道防線,Apk防護措施,資料加密,逆向工具的原理,例項等多方面進行闡述。

資料庫——mysql鎖機制

(一)引言                                                                                                                          MySQL引擎預設的鎖級別: MyISAM和MEMORY

AngularJSui-sref如何傳遞引數

平時有些引數我們放在url裡面可以傳遞到下一個頁面,只需加上字串 "?args1=1&agrs2=2" 即可 但是在angular-ui-router中,我們通過ui-sref控制頁面跳轉,此時應該如何傳遞引數 ui-sref傳遞引數寫法: ui-sref

PAT1081. 檢查密碼 (15)C語言實現

簡單邏輯題。#include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> int main() { int n; int i; c

Java8 resize() 機制

HashMap的擴容機制---resize()原文連結: https://blog.csdn.net/qq_27093465/article/details/52270519雖然在hashmap的原理裡面有這段,但是這個單獨拿出來講rehash或者resize()也是極好的。

AngularJS過濾陣列中的子集(每一個子項都過濾)

說白了就是filter+repeat; 原始碼: <!DOCTYPE html> <html> <head> <meta charset="utf-8"&

Angularjsng-disabled

定義和用法 ng-disabled 指令設定表單輸入欄位的 disabled 屬性(input, select, 或 textarea)。 如果 ng-disabled 中的表示式返回 true 則