Angular中ngModel的$render的详解
在我開始著手ngModel的領(lǐng)域時候,有一個問題很令我糾結(jié),那就是$render()到底是做什么的呢?查了很多資料都只是簡單的描述一下,這就令我很糾結(jié)了,終于在一個陽光明媚的晚上,我終于解決了這個大問題
那么這個$render方法到底是干什么的呢?他的用處就是在$viewValue改變的時候可以重新綁定model數(shù)據(jù),但是我們要注意一點(diǎn)($viewValue和DOM節(jié)點(diǎn)的value是不同的),我覺得他們的區(qū)別有點(diǎn)類似setTimeout和$timeout的區(qū)別,但是又不太一樣。ps:其實(shí)modelValue和綁定的數(shù)據(jù)也可以不同
Input里面模型的值:{{vm.modelTest}} <input type="text" ng-model="vm.modelTest" model-render> View Code .directive('modelRender', function () {return {require: 'ngModel',link: function (scope, iElm, iAttrs, ngModelCtrl) {iElm.on('mouseenter', function () {//嘗試注釋iElm.val(1);console.log(ngModelCtrl);//嘗試注釋ngModelCtrl.$setViewValue(11);console.log(ngModelCtrl);//嘗試注釋 ngModelCtrl.$render();console.log(ngModelCtrl);}) }}}) View Code?我們分幾種情況分析
這是鼠標(biāo)沒有經(jīng)過指令的時候的樣子
1.當(dāng)我們使用js原生方法設(shè)置input的val值的時候,并且不執(zhí)行$render函數(shù),我們可以看到input里面的model值是沒有變化的,但是input的的value是變成了1,而且我們看到不僅model值沒有變化,ngModel的$viewValue和$modelValue同樣也沒有變化。我們可以得出結(jié)論 (input的value值不一定等于$viewValue)
結(jié)果是這樣的
-----------------------------------------------------------------------------------------------------------------------
然后,我們嘗試在執(zhí)行js原生改變value值之后,執(zhí)行$render函數(shù)是個什么樣的狀況,
看完上面的實(shí)驗(yàn)之后我們發(fā)現(xiàn)input的value值并沒有發(fā)生變化,也就是說js原生改變input的value值是無效的,那么在這里我們就可以看到$render的功能了。
我們可以大膽的預(yù)計(jì)$render的功能跟$apply的功能是一致的,我們在上一章講過,$apply是以viewValue為主,讓modelValue變成viewValue,也就是modelValue -> viewValue,那么$render是不是以modelValue為主,讓viewValue->modelValue呢?
-------------------------------------------------------------------------------------------------------------------------
2.接下來我們嘗試,使用ng原生改變 也就是說$setviewValue,是如何表現(xiàn)的呢?
現(xiàn)在我們注釋掉js原生改變value的方法,而去使用$setViewValue,并且不執(zhí)行$render函數(shù),直接上結(jié)果,我們看到,執(zhí)行完$setViewValue之后,無論是viewValue和modelValue都是已經(jīng)同步了,但是input里面的值卻依然是test,在這里我們再次驗(yàn)證了那個說法($viewValue和DOM節(jié)點(diǎn)的value是不同的)
現(xiàn)在我們在$setViewValue之后使用,$render()看看是什么效果,
大家發(fā)現(xiàn)了吧,$render的功能和$apply的功能極為相似,但是是不是很多人在講$render的時候,都會說model同步到view,我覺得這個說法不太對,我測試過在click事件用非常規(guī)手段改變controller中model的值,發(fā)現(xiàn)就算controller的值已經(jīng)改變了,但是ngModel的值無論是viewValue還是modelValue都沒有變化,然后嘗試用$modelValue的屬性強(qiáng)行改變$modelValue,結(jié)果還是沒作用。我們下面來看看$render的源碼
ctrl.$render = function() {element.val(ctrl.$isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);};這是其中一個,$render在不同的指令下的代碼都不太一樣,但是其作用基本一致,但是從這里我們就可以看出$render的到底在干什么事了。那么$render什么時候觸發(fā)呢?其實(shí)看你自己想什么時候調(diào)用它,你可以覆蓋他的方法,重寫,在$watch也好,$viewChange也好。默認(rèn)的觸發(fā)事件一些特別input的value改變的時候例如單選,還有rollbackView()的時候
另外一個真正體現(xiàn)$render執(zhí)行事件的源代碼在這里,里面我寫了注釋,大家應(yīng)該都能懂
$scope.$watch(function ngModelWatch() {//解析ngModel的表達(dá)式,獲取內(nèi)容var modelValue = ngModelGet($scope);// if scope model value and ngModel value are out of sync// TODO(perf): why not move this to the action fn?//判斷表達(dá)式的值是否跟modelValue一致if (modelValue !== ctrl.$modelValue &&// checks for NaN is needed to allow setting the model to NaN when there's an asyncValidator(ctrl.$modelValue === ctrl.$modelValue || modelValue === modelValue)) {//更新modelValue的值ctrl.$modelValue = ctrl.$$rawModelValue = modelValue;parserValid = undefined;//獲取管道信息var formatters = ctrl.$formatters,idx = formatters.length;var viewValue = modelValue;while (idx--) {viewValue = formatters[idx](viewValue);}//如果viewValue和ModelValue不一致if (ctrl.$viewValue !== viewValue) {ctrl.$viewValue = ctrl.$$lastCommittedViewValue = viewValue;ctrl.$render();ctrl.$$runValidators(modelValue, viewValue, noop);}}//返回解析的表達(dá)式return modelValue;}); }]; 好了,$render就已經(jīng)講完了,這是作者的原創(chuàng)帖,如轉(zhuǎn)載 請注明,最后貼段代碼感受下
轉(zhuǎn)載于:https://www.cnblogs.com/HeJason/p/5486991.html
總結(jié)
以上是生活随笔為你收集整理的Angular中ngModel的$render的详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: stm32学习笔记----双串口同时打开
- 下一篇: php artisan 命令