首頁 web前端 js教程 angular1學習筆記,裡面有angularjs中的view model同步過程

angular1學習筆記,裡面有angularjs中的view model同步過程

Sep 07, 2018 pm 05:28 PM
angularjs javascript

這算是一篇個人對angularjs的理解筆記吧,這裡有view model的同步過程,寫給大家看看吧,現在就讓我們一起進入本篇文章吧

事情起源於在專案中遇到的一個小問題:專案中需要一個輸入框輸入賣出產品數量,並且在使用者輸入後根據輸入資料計算手續費。很自然的我用了ng-model和ng-change,而且一般情況下沒什麼問題。問題是:輸入框下方還有一個按鈕是全部賣出,點選這個按鈕程式會自動設定賣出額。但實際上這時程式並沒有計算手續費。
經過排查並查閱文件之後,發現是ng-change的問題。 Angular關於ng-change的官方文件的提示是:
The expression is not evaluated when the value change is coming from the model.
ng-change的源碼也很簡單:

  var ngChangeDirective = valueFn({
      restrict: 'A',
      require: 'ngModel',
      link: function(scope, element, attr, ctrl) {
        ctrl.$viewChangeListeners.push(function() {
          scope.$eval(attr.ngChange);
        });
      }
    });
登入後複製

從中我們也可以看出ng-change只做了view到model的監聽。所以當我們直接在js修改ng-model的變數時並不會觸發ng-change。
問題找到了,解決方案也不難,放棄ng-change,改用$watch就行了。
但是就這麼結束了嗎?一個變數從view變化開始到同步更新到model到底經歷了什麼?反過來呢,是一樣的嗎?
所以我又去看了看ng-model的源碼,並沒有什麼收穫,不過意外的了解到了這麼個點:
ng-change是在model值變化之前執行的。 ng-model原始碼中有這麼個函數:

function setupModelWatcher(ctrl) {
  // model -> value
  // !!!Note: we cannot use a normal scope.$watch as we want to detect the following:
  // !!!1. scope value is 'a'
  // !!! 2. user enters 'b'
  // !!!3. ng-change kicks in and reverts scope value to 'a'
  //    -> scope value did not change since the last digest as
  //       ng-change executes in apply phase
  // !!!4. view should be changed back to 'a'
  ctrl.$$scope.$watch(function ngModelWatch(scope) {
    var modelValue = ctrl.$$ngModelGet(scope);

    // if scope model value and ngModel value are out of sync
    // This cannot be moved to the action function, because it would not catch the
    // case where the model is changed in the ngChange function or the model setter
    if (modelValue !== ctrl.$modelValue &&
      // checks for NaN is needed to allow setting the model to NaN when there's an asyncValidator
      // eslint-disable-next-line no-self-compare
      (ctrl.$modelValue === ctrl.$modelValue || modelValue === modelValue)
    ) {
      ctrl.$$setModelValue(modelValue);
    }

    return modelValue;
  });
}
登入後複製

裡面的註解解釋了為什麼變數model值的修改要在ng-change之後,因為ng-change中很可能會把變數的值又修改回去,這樣變數值事實上就沒改變(寫api真的是什麼情況都要考慮到啊!!)。關於這一點,以及前面的問題這裡有一個demo程式碼:http://php.cn/course/47.html

既然看原始碼沒什麼收穫,那就上網搜搜文章看看吧。這個過程中找到一篇很好的文章,這篇文章介紹了

$formatters,$parsers,$render以及$setViewValue。這裡就不再介紹了,如果需要學習,原文在這裡:http://php.cn/course/47.html

在學習$setViewValue時也發現一個很容易被坑的點:在呼叫$setViewValue時,如果參數是引用變量,那麼如果引用變數位址沒變,則這個變數被認為沒有改變,如var map = ['er', 'tr '];那麼map.pop();之後$setViewValue不認為map值改變了。關於這個具體可以看​​我對這個問題的回答。 (想看更多就到PHP中文網AngularJS開發手冊中學習)

ng-model也有這個問題,這個在ng-model原始碼註解中可以看到:

However, custom controls might also pass objects to this method. In
this case, we should make a copy of the object before passing it to
$setViewValue. This is because ngModel does not perform a deep
watch of objects, it only looks for a change of identity.

If you only change the property of the object then Model will willnotngize that the object has changed and will not invoke the
$parsersand
$validators pipelines.

#從上面也可以看到其實一個變數的更新由view到model和model到view不只

$formatters$parsers管道,那麼還有哪些呢?

在查了一圈資料後找到一個很清楚的解釋:https://stackoverflow.com/que...,大家其實只需要看問題的回答,問題實在太長了。 。 。

這個回答中有個demo鏈接,我copy了一下並做了寫小修改放在這個地址了:http://php.cn/course/47.html,這個demo很清晰的顯示了變量更新的過程,細節就不再累述了,這裡只把結果總結如下:
從model到view:
model值修改---->
$formatters管道--- -> $render函數----> $validators ----> $watch函數

從view到model:

view值修改---->
$setViewValue函數----> $parsers管道----> $validators ----> $viewChangeListener函數----> $watch函數我們也可以直接呼叫
$setViewValue函數去直接改變$viewValue 的值,流程會跟上面一樣。 注意在使用
$setViewValue時一定要警惕參數是引用變數的情況,這個坑在上文也已經提到了。

本文沒有具體介紹

$formatters$parsers 管道,關於這部分可以參考文中給出的連結

好了,這篇文章到這就結束了(想看更多就到PHP中文網AngularJS使用手冊中學習),有問題的可以在下方留言提問。

#

以上是angular1學習筆記,裡面有angularjs中的view model同步過程的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱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

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

熱工具

記事本++7.3.1

記事本++7.3.1

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

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

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

如何使用WebSocket和JavaScript實現線上語音辨識系統 如何使用WebSocket和JavaScript實現線上語音辨識系統 Dec 17, 2023 pm 02:54 PM

如何使用WebSocket和JavaScript實現線上語音辨識系統引言:隨著科技的不斷發展,語音辨識技術已成為了人工智慧領域的重要組成部分。而基於WebSocket和JavaScript實現的線上語音辨識系統,具備了低延遲、即時性和跨平台的特點,成為了廣泛應用的解決方案。本文將介紹如何使用WebSocket和JavaScript來實現線上語音辨識系

WebSocket與JavaScript:實現即時監控系統的關鍵技術 WebSocket與JavaScript:實現即時監控系統的關鍵技術 Dec 17, 2023 pm 05:30 PM

WebSocket與JavaScript:實現即時監控系統的關鍵技術引言:隨著互聯網技術的快速發展,即時監控系統在各個領域中得到了廣泛的應用。而實現即時監控的關鍵技術之一就是WebSocket與JavaScript的結合使用。本文將介紹WebSocket與JavaScript在即時監控系統中的應用,並給出程式碼範例,詳細解釋其實作原理。一、WebSocket技

如何利用JavaScript和WebSocket實現即時線上點餐系統 如何利用JavaScript和WebSocket實現即時線上點餐系統 Dec 17, 2023 pm 12:09 PM

如何利用JavaScript和WebSocket實現即時線上點餐系統介紹:隨著網路的普及和技術的進步,越來越多的餐廳開始提供線上點餐服務。為了實現即時線上點餐系統,我們可以利用JavaScript和WebSocket技術。 WebSocket是一種基於TCP協定的全雙工通訊協議,可實現客戶端與伺服器的即時雙向通訊。在即時線上點餐系統中,當使用者選擇菜餚並下訂單

如何使用WebSocket和JavaScript實現線上預約系統 如何使用WebSocket和JavaScript實現線上預約系統 Dec 17, 2023 am 09:39 AM

如何使用WebSocket和JavaScript實現線上預約系統在當今數位化的時代,越來越多的業務和服務都需要提供線上預約功能。而實現一個高效、即時的線上預約系統是至關重要的。本文將介紹如何使用WebSocket和JavaScript來實作一個線上預約系統,並提供具體的程式碼範例。一、什麼是WebSocketWebSocket是一種在單一TCP連線上進行全雙工

JavaScript與WebSocket:打造高效率的即時天氣預報系統 JavaScript與WebSocket:打造高效率的即時天氣預報系統 Dec 17, 2023 pm 05:13 PM

JavaScript和WebSocket:打造高效的即時天氣預報系統引言:如今,天氣預報的準確性對於日常生活以及決策制定具有重要意義。隨著技術的發展,我們可以透過即時獲取天氣數據來提供更準確可靠的天氣預報。在本文中,我們將學習如何使用JavaScript和WebSocket技術,來建立一個高效的即時天氣預報系統。本文將透過具體的程式碼範例來展示實現的過程。 We

簡易JavaScript教學:取得HTTP狀態碼的方法 簡易JavaScript教學:取得HTTP狀態碼的方法 Jan 05, 2024 pm 06:08 PM

JavaScript教學:如何取得HTTP狀態碼,需要具體程式碼範例前言:在Web開發中,經常會涉及到與伺服器進行資料互動的場景。在與伺服器進行通訊時,我們經常需要取得傳回的HTTP狀態碼來判斷操作是否成功,並根據不同的狀態碼來進行對應的處理。本篇文章將教你如何使用JavaScript來取得HTTP狀態碼,並提供一些實用的程式碼範例。使用XMLHttpRequest

javascript如何使用insertBefore javascript如何使用insertBefore Nov 24, 2023 am 11:56 AM

用法:在JavaScript中,insertBefore()方法用於在DOM樹中插入一個新的節點。這個方法需要兩個參數:要插入的新節點和參考節點(即新節點將要插入的位置的節點)。

如何在JavaScript中取得HTTP狀態碼的簡單方法 如何在JavaScript中取得HTTP狀態碼的簡單方法 Jan 05, 2024 pm 01:37 PM

JavaScript中的HTTP狀態碼取得方法簡介:在進行前端開發中,我們常常需要處理與後端介面的交互,而HTTP狀態碼就是其中非常重要的一部分。了解並取得HTTP狀態碼有助於我們更好地處理介面傳回的資料。本文將介紹使用JavaScript取得HTTP狀態碼的方法,並提供具體程式碼範例。一、什麼是HTTP狀態碼HTTP狀態碼是指當瀏覽器向伺服器發起請求時,服務

See all articles