搜尋
首頁web前端js教程掌握$ Watch在Angularjs

掌握$ Watch在Angularjs

Feb 18, 2025 am 10:47 AM

Mastering $watch in AngularJS

核心要點

  • AngularJS中的$watch函數是觀察變量值或表達式變化的強大工具。檢測到變化時,它會觸發一個回調函數,該函數會在每次被監視的變量發生變化時執行。
  • $watch使用JavaScript的相等運算符(===)進行比較。如果新值與舊值不同,則觸發回調函數。但是,需要注意的是,默認情況下,$watch只檢查引用相等性,這意味著只有當為被監視的變量分配新值時,才會觸發回調函數。
  • AngularJS還提供$watchGroup$watchCollection作為方便的快捷方式,分別用於設置具有相同回調函數的多個監視器或監視數組或對象。但是,這些方法只執行淺監視,只對引用更改做出反應。
  • 使用$watch,尤其是在多個變量上使用,可能會影響性能,因為需要在每個摘要周期中檢查所有被監視變量的變化。開發人員應根據情況考慮使用$watchGroup$watchCollection,或限制被監視變量的數量以提高性能。

本文由Mark Brown同行評審。感謝所有SitePoint的同行評審員,使SitePoint的內容達到最佳狀態!

AngularJS提供了許多不同的選項,可以通過三種不同的“watch”方法使用發布-訂閱模式。每種方法都採用可選參數來修改其行為。

關於$watch的官方文檔遠非詳盡:畢竟,這是一個困擾AngularJS v1整體的問題。即使是解釋如何進行的在線資源,充其量也是零散的。

因此,最終,開發人員很難為特定情況選擇正確的方法。對於AngularJS初學者來說尤其如此!結果可能會令人驚訝或不可預測,這不可避免地會導致錯誤。

在本文中,我將假設您熟悉AngularJS概念。如果您覺得需要復習,您可能需要閱讀有關$scope、綁定以及$apply$digest的內容。

檢查您的理解

例如,監視數組的第一個元素的最佳方法是什麼?假設我們在我們的作用域上聲明了一個數組,$scope.letters = ['A','B','C']

  • 當我們向數組添加元素時,$scope.$watch('letters', function () {...});是否會觸發其回調函數?
  • 當我們更改其第一個元素時,它會觸發嗎?
  • $scope.$watch('letters[0]', function () {...});呢?它會以相同的方式工作,還是更好?
  • 在上面,數組元素是原始值:如果我們用相同的值替換第一個元素會怎樣?
  • 現在假設數組包含對象:會發生什麼?
  • $watch$watchCollection$watchGroup之間有什麼區別?

如果您對所有這些問題感到困惑,請繼續閱讀。我的目標是通過幾個示例盡可能清楚地說明這一點,從而引導您完成整個過程。

$scope.$watch

讓我們從$scope.$watch開始。這是所有watch功能的核心:我們將看到的每種其他方法都只是$watch的便捷快捷方式。

使用$watch

現在,Angular的優點是您可以顯式地使用相同的機制在控制器中執行由數據更改觸發的複雜操作。例如,您可以對某些數據設置監視器,這些數據可以響應以下內容而更改:

  1. 超時
  2. UI
  3. 由Web Worker執行的複雜異步計算
  4. Ajax調用

您可以只設置一個偵聽器來處理任何數據更改,無論是什麼原因造成的。

但是,要這樣做,您需要自己調用$scope.$watch

實踐操作

讓我們看看$rootscope.watch()的代碼。

這是它的簽名:function(watchExp, listener, objectEquality, prettyPrintExpression)

詳細來說,它的四個參數:

  1. watchExp 被監視的表達式。它可以是函數或字符串,它在每個摘要周期中都會被評估。

    這裡需要注意的一個關鍵方面是,如果表達式被評估為函數,則該函數需要是冪等的。換句話說,對於相同的輸入集,它應該始終返回相同的輸出。如果不是這種情況,Angular將假設被監視的數據已更改。反過來,這意味著它將繼續檢測差異並在摘要周期的每次迭代中調用偵聽器。

  2. listener 一個回調函數,在首次設置監視器時觸發,然後在摘要周期中每次檢測到watchExp值的更改時觸發。設置時的初始調用旨在為表達式存儲初始值。

  3. objectEquality 當且僅當此值為true時,監視器將執行深度比較。否則,它執行淺比較,即僅比較引用。

    讓我們以數組為例:$scope.fruit = ["banana", "apple"]

    objectEquality == false意味著只有重新分配fruit字段才會導致調用偵聽器。

    我們還需要檢查“深度”比較有多深:我們稍後會討論這一點。

  4. prettyPrintExpression 如果傳遞,它將覆蓋監視表達式。此參數並非旨在在對$watch()的正常調用中使用;它由表達式解析器內部使用。

    小心:正如您自己所看到的,當意外傳遞第四個參數時,很容易出現意外的結果。

現在我們準備回答引言中的一些問題。請查看本節的示例:

CodePen 示例

請隨意熟悉它們;您可以直接比較行為差異,或按照文章中的順序進行。

監視數組

因此,您需要監視作用域上的數組以進行更改,但是“更改”是什麼意思?

假設您的控制器看起來像這樣:

app.controller('watchDemoCtrl', ['$scope', function($scope){
    $scope.letters = ['A','B','C'];
}]);

一種選擇是使用這樣的調用:

$scope.$watch('letters', function (newValue, oldValue, scope) {
    // 对 $scope.letters 执行任何操作
});

在上面的回調中,newValueoldValue具有不言自明的含義,並且每次$digest週期調用它時都會更新。 scope的含義也很直觀,因為它保存對當前作用域的引用。

但是,關鍵是:何時會調用此偵聽器?事實上,您可以添加、刪除、替換letters數組中的元素,而不會發生任何事情。這是因為,默認情況下,$watch假定您只想要引用相等性,因此只有當您為$scope.letters分配新值時,才會觸發回調函數。

如果您需要對數組的任何元素的更改採取行動,則需要將true作為第三個參數傳遞給watch(即作為上面描述的可選objectEquality參數的值)。

$scope.$watch('letters', function (newValue, oldValue, scope) {
    // 对 $scope.letters 执行任何操作
}, true);

監視對象

對於對象,情況沒有改變:如果objectEquality為false,您只需監視對該作用域變量的任何重新賦值,而如果為true,則每次更改對像中的元素時都會觸發回調函數。

監視數組的第一個元素

值得注意的是,通過使用objectEquality === true監視數組,每次觸發回調函數時,newValueoldValue將是整個數組的新舊值。因此,您必須將它們彼此進行比較才能了解實際發生了什麼變化。

假設您只對數組中第一個元素(或第四個元素——原理相同)的更改感興趣。由於Angular非常出色,它允許您這樣做:您可以在作為第一個參數傳遞給$watch的表達式中以自然的方式表達它:

$scope.$watch('letters[4]', function (newValue, oldValue, scope) {
    //...
}, true);

如果數組只有2個元素會怎樣?沒問題,除非您添加第四個元素,否則您的回調函數不會被觸發。好吧,好的,從技術上講,它會在您設置監視器時觸發,然後只有在您添加第四個元素時才會觸發。

如果您記錄oldValue,您會看到在這兩種情況下它都將是未定義的。將此與監視現有元素時發生的情況進行比較:在設置時,您仍然有oldValue == undefined。所以$watch無法處理!

現在一個更有趣的問題:我們在這裡需要傳遞objectEquality === true嗎?

簡短的回答:對不起,沒有簡短的回答。

這確實取決於:

  • 在此示例中,由於我們正在處理原始值,因此我們不需要深度比較,因此我們可以省略objectEquality
  • 但是,假設我們有一個矩陣,例如$scope.board = [[1, 2, 3], [4, 5, 6]];,並且我們想監視第一行。然後我們可能希望在像$scope.board[0][1] = 7這樣的賦值更改它時收到警報。

監視對象的字段

也許比監視數組中的任意元素更有用的是,我們可以監視對像中的任意字段。但這並不奇怪,對吧?畢竟,JavaScript中的數組對象。

app.controller('watchDemoCtrl', ['$scope', function($scope){
    $scope.letters = ['A','B','C'];
}]);

深度比較有多深?

在這一點上,我們還需要闡明最後一個但至關重要的細節:如果我們需要監視一個複雜的嵌套對象,其中每個字段都是非原始值,會發生什麼?例如樹或圖,或者只是一些JSON數據。

讓我們檢查一下!

首先,我們需要一個要監視的對象:

$scope.$watch('letters', function (newValue, oldValue, scope) {
    // 对 $scope.letters 执行任何操作
});

讓我們為整個對象設置監視器:我認為,到目前為止,很清楚的是,在這種情況下必須將objectEquality設置為true

$scope.$watch('letters', function (newValue, oldValue, scope) {
    // 对 $scope.letters 执行任何操作
}, true);

問題是:如果像$scope.b.bb[1].bb2a = 7;這樣的賦值發生,Angular是否會足夠好心地讓我們知道?

答案是:是的,幸運的是,它會(在之前的CodePen演示中查看)。

其他方法

$scope.$watchGroup

$watchGroup()真的是一種不同的方法嗎?答案是否定的,它不是。

$watchGroup()是一個方便的快捷方式,允許您使用相同的回調函數設置多個監視器,並傳遞一個watchExpressions數組。

每個傳遞的表達式都將使用標準$scope.$watch()方法進行監視。

$scope.$watch('letters[4]', function (newValue, oldValue, scope) {
    //...
}, true);

值得注意的是,使用$watchGroupnewValuesoldValues將保存表達式的值列表,包括發生更改的值和保持相同值的那些值,順序與它們在第一個參數的數組中傳遞的順序相同。

如果您檢查了此方法的文檔,您可能會注意到它沒有採用objectEquality選項。這是因為它淺監視表達式,並且只對引用更改做出反應。

如果您使用下面的$watchGroup()演示進行操作,您可能會對一些細微之處感到驚訝。例如,unshift將導致調用偵聽器,至少在某種程度上是這樣:這是因為當將表達式列表傳遞給$watchGroup時,任何一個表達式觸發都會導致執行回調函數。

CodePen 示例

此外,請注意,$scope.obj.b的任何子字段的任何更改都不會產生任何更新——只有為b字段本身分配新值才會產生更新。

$scope.$watchCollection

這是監視數組或對象的另一個便捷快捷方式。對於數組,當替換、刪除或添加任何元素時,將調用偵聽器。對於對象,當更改任何屬性時。同樣,$watchCollection()不允許objectEquality,因此它只會淺監視元素/字段,並且不會對它們的子字段的更改做出反應。

CodePen 示例

結論

希望這些示例能幫助您發現此Angular功能的強大功能,並了解使用正確的選項有多麼重要。

隨意複製CodePen並嘗試在不同的上下文中使用這些方法,並且不要忘記在評論區留下您的反饋!

如果您想更深入地了解我們在本文中討論的一些概念,以下是一些進一步閱讀的建議:

  1. AngularJS作用域
  2. 理解Angular的$apply()$digest()
  3. JavaScript事件處理中的新興模式
  4. AngularJS作用域中的原型繼承
  5. $watch等的文檔

關於在AngularJS中掌握$watch的常見問題解答 (FAQ)

$watch在AngularJS中的主要目的是什麼?

AngularJS中的$watch函數主要用於觀察變量或表達式的值的變化。它是AngularJS作用域對象的一部分,用於監視變量或表達式的值的變化。檢測到變化時,$watch函數會觸發一個回調函數,該函數會在每次被監視的變量發生變化時執行。

$watch在AngularJS中是如何工作的?

AngularJS中的$watch函數通過比較被監視變量或表達式的舊值和新值來工作。它使用JavaScript的相等運算符(===)進行比較。如果新值與舊值不同,$watch函數將觸發回調函數。

我如何在AngularJS中使用$watch

要在AngularJS中使用$watch,您需要在作用域對像上調用$watch方法,並向其傳遞兩個參數:要監視的變量或表達式的名稱,以及在被監視的變量發生變化時要執行的回調函數。這是一個示例:

app.controller('watchDemoCtrl', ['$scope', function($scope){
    $scope.letters = ['A','B','C'];
}]);

$watch$apply在AngularJS中的區別是什麼?

AngularJS中的$watch函數用於觀察變量或表達式的變化,而$apply函數用於手動啟動AngularJS摘要周期,該週期會檢查被監視變量的任何變化並相應地更新視圖。 $apply函數通常在AngularJS上下文之外進行模型更改時使用,例如在DOM事件處理程序或setTimeout函數中。

我可以使用$watch在AngularJS中監視多個變量嗎?

是的,您可以使用$watch在AngularJS中監視多個變量。您可以通過將變量名稱數組傳遞給$watch函數來實現此目的。但是,請記住,監視多個變量可能會影響性能,因為$watch函數需要在每個摘要周期中檢查所有被監視變量的變化。

我如何在AngularJS中停止監視$watch中的變量?

當您在AngularJS中調用$watch函數時,它會返回一個註銷函數。您可以調用此函數來停止監視變量。這是一個示例:

$scope.$watch('letters', function (newValue, oldValue, scope) {
    // 对 $scope.letters 执行任何操作
});

AngularJS中的$watchGroup是什麼?

AngularJS中的$watchGroup函數用於監視一組表達式。它的工作方式類似於$watch函數,但它只在每個摘要周期觸發一次回調函數,即使多個被監視的表達式發生了變化也是如此。這可以在監視多個表達式時提高性能。

AngularJS中的$watchCollection是什麼?

AngularJS中的$watchCollection函數用於監視對象的屬性或數組的元素。只要任何屬性或元素發生變化,它就會觸發回調函數,但與$watch不同,它不會深度監視對像或數組,這可以提高性能。

我可以在AngularJS指令中使用$watch嗎?

是的,您可以在AngularJS指令中使用$watch。事實上,在指令中使用$watch來響應指令的屬性或作用域變量的變化是一種常見的做法。

使用$watch在AngularJS中有哪些性能方面的考慮?

使用$watch在AngularJS中可能會影響性能,尤其是在監視許多變量或表達式時。這是因為$watch函數需要在每個摘要周期中檢查所有被監視變量的變化。為了提高性能,請根據情況考慮使用$watchGroup$watchCollection,或限制被監視變量的數量。

以上是掌握$ Watch在Angularjs的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
JavaScript的核心:它是在C還是C上構建的?JavaScript的核心:它是在C還是C上構建的?May 05, 2025 am 12:07 AM

javascriptisnotbuiltoncorc; sanInterpretedlanguagethatrunsonenginesoftenwritteninc.1)JavascriptwasdesignedAsignedAsalightWeight,drackendedlanguageforwebbrowsers.2)Enginesevolvedfromsimpleterterpretpretpretpretpreterterpretpretpretpretpretpretpretpretpretcompilerers,典型地,替代品。

JavaScript應用程序:從前端到後端JavaScript應用程序:從前端到後端May 04, 2025 am 12:12 AM

JavaScript可用於前端和後端開發。前端通過DOM操作增強用戶體驗,後端通過Node.js處理服務器任務。 1.前端示例:改變網頁文本內容。 2.後端示例:創建Node.js服務器。

Python vs. JavaScript:您應該學到哪種語言?Python vs. JavaScript:您應該學到哪種語言?May 03, 2025 am 12:10 AM

選擇Python還是JavaScript應基於職業發展、學習曲線和生態系統:1)職業發展:Python適合數據科學和後端開發,JavaScript適合前端和全棧開發。 2)學習曲線:Python語法簡潔,適合初學者;JavaScript語法靈活。 3)生態系統:Python有豐富的科學計算庫,JavaScript有強大的前端框架。

JavaScript框架:為現代網絡開發提供動力JavaScript框架:為現代網絡開發提供動力May 02, 2025 am 12:04 AM

JavaScript框架的強大之處在於簡化開發、提升用戶體驗和應用性能。選擇框架時應考慮:1.項目規模和復雜度,2.團隊經驗,3.生態系統和社區支持。

JavaScript,C和瀏覽器之間的關係JavaScript,C和瀏覽器之間的關係May 01, 2025 am 12:06 AM

引言我知道你可能會覺得奇怪,JavaScript、C 和瀏覽器之間到底有什麼關係?它們之間看似毫無關聯,但實際上,它們在現代網絡開發中扮演著非常重要的角色。今天我們就來深入探討一下這三者之間的緊密聯繫。通過這篇文章,你將了解到JavaScript如何在瀏覽器中運行,C 在瀏覽器引擎中的作用,以及它們如何共同推動網頁的渲染和交互。 JavaScript與瀏覽器的關係我們都知道,JavaScript是前端開發的核心語言,它直接在瀏覽器中運行,讓網頁變得生動有趣。你是否曾經想過,為什麼JavaScr

node.js流帶打字稿node.js流帶打字稿Apr 30, 2025 am 08:22 AM

Node.js擅長於高效I/O,這在很大程度上要歸功於流。 流媒體匯總處理數據,避免內存過載 - 大型文件,網絡任務和實時應用程序的理想。將流與打字稿的類型安全結合起來創建POWE

Python vs. JavaScript:性能和效率注意事項Python vs. JavaScript:性能和效率注意事項Apr 30, 2025 am 12:08 AM

Python和JavaScript在性能和效率方面的差異主要體現在:1)Python作為解釋型語言,運行速度較慢,但開發效率高,適合快速原型開發;2)JavaScript在瀏覽器中受限於單線程,但在Node.js中可利用多線程和異步I/O提升性能,兩者在實際項目中各有優勢。

JavaScript的起源:探索其實施語言JavaScript的起源:探索其實施語言Apr 29, 2025 am 12:51 AM

JavaScript起源於1995年,由布蘭登·艾克創造,實現語言為C語言。 1.C語言為JavaScript提供了高性能和系統級編程能力。 2.JavaScript的內存管理和性能優化依賴於C語言。 3.C語言的跨平台特性幫助JavaScript在不同操作系統上高效運行。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

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

熱工具

Atom編輯器mac版下載

Atom編輯器mac版下載

最受歡迎的的開源編輯器

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SecLists

SecLists

SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

mPDF

mPDF

mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),