angular1學習筆記,裡面有angularjs中的view model同步過程
這算是一篇個人對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#從上面也可以看到其實一個變數的更新由view到model和model到view不只
this case, we should make a copy of the object before passing it to$setViewValue
. This is becausengModel
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
$validatorspipelines.
$formatters和
$parsers管道,那麼還有哪些呢?
這個回答中有個demo鏈接,我copy了一下並做了寫小修改放在這個地址了:http://php.cn/course/47.html,這個demo很清晰的顯示了變量更新的過程,細節就不再累述了,這裡只把結果總結如下:
從model到view:
model值修改---->
$formatters管道--- ->
$render函數---->
$validators ---->
$watch函數
view值修改---->
$setViewValue函數---->
$parsers管道---->
$validators ---->
$viewChangeListener函數---->
$watch函數
我們也可以直接呼叫
$setViewValue函數去直接改變
$viewValue 的值,流程會跟上面一樣。
注意在使用
$setViewValue時一定要警惕參數是引用變數的情況,這個坑在上文也已經提到了。
$formatters 和
$parsers 管道,關於這部分可以參考文中給出的連結
好了,這篇文章到這就結束了(想看更多就到PHP中文網AngularJS使用手冊中學習),有問題的可以在下方留言提問。
#以上是angular1學習筆記,裡面有angularjs中的view model同步過程的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

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

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

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

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

熱門文章

熱工具

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

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

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

Dreamweaver CS6
視覺化網頁開發工具

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

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

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

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

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

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

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

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

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