浅谈Angular中ngModel的$render
在我开始着手ngmodel的领域时候,有一个问题很令我纠结,那就是$render()到底是做什么的呢?查了很多资料都只是简单的描述一下,这就令我很纠结了,终于在一个阳光明媚的晚上,我终于解决了这个大问题
那么这个$render方法到底是干什么的呢?他的用处就是在$viewvalue改变的时候可以重新绑定model数据,但是我们要注意一点($viewvalue和dom节点的value是不同的),我觉得他们的区别有点类似settimeout和$timeout的区别,但是又不太一样。ps:其实modelvalue和绑定的数据也可以不同
input里面模型的值:{{vm.modeltest}} <input type="text" ng-model="vm.modeltest" model-render>
.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); }) } } })
我们分几种情况分析
这是鼠标没有经过指令的时候的样子
1.当我们使用js原生方法设置input的val值的时候,并且不执行$render函数,我们可以看到input里面的model值是没有变化的,但是input的的value是变成了1,而且我们看到不仅model值没有变化,ngmodel的$viewvalue和$modelvalue同样也没有变化。我们可以得出结论 (input的value值不一定等于$viewvalue)
结果是这样的
--------------------------------------------------------------------------
然后,我们尝试在执行js原生改变value值之后,执行$render函数是个什么样的状况,
看完上面的实验之后我们发现input的value值并没有发生变化,也就是说js原生改变input的value值是无效的,那么在这里我们就可以看到$render的功能了。
我们可以大胆的预计$render的功能跟$apply的功能是一致的,我们在上一章讲过,$apply是以viewvalue为主,让modelvalue变成viewvalue,也就是modelvalue -> viewvalue,那么$render是不是以modelvalue为主,让viewvalue->modelvalue呢?
-------------------------------------------------------------------------------------------------
2.接下来我们尝试,使用ng原生改变 也就是说$setviewvalue,是如何表现的呢?
现在我们注释掉js原生改变value的方法,而去使用$setviewvalue,并且不执行$render函数,直接上结果,我们看到,执行完$setviewvalue之后,无论是viewvalue和modelvalue都是已经同步了,但是input里面的值却依然是test,在这里我们再次验证了那个说法($viewvalue和dom节点的value是不同的)
现在我们在$setviewvalue之后使用,$render()看看是什么效果,
大家发现了吧,$render的功能和$apply的功能极为相似,但是是不是很多人在讲$render的时候,都会说model同步到view,我觉得这个说法不太对,我测试过在click事件用非常规手段改变controller中model的值,发现就算controller的值已经改变了,但是ngmodel的值无论是viewvalue还是modelvalue都没有变化,然后尝试用$modelvalue的属性强行改变$modelvalue,结果还是没作用。
我们下面来看看$render的源码
ctrl.$render = function() { element.val(ctrl.$isempty(ctrl.$viewvalue) ? '' : ctrl.$viewvalue); };
这是其中一个,$render在不同的指令下的代码都不太一样,但是其作用基本一致,但是从这里我们就可以看出$render的到底在干什么事了。那么$render什么时候触发呢?其实看你自己想什么时候调用它,你可以覆盖他的方法,重写,在$watch也好,$viewchange也好。默认的触发事件一些特别input的value改变的时候例如单选,还有rollbackview()的时候
另外一个真正体现$render执行事件的源代码在这里,里面我写了注释,大家应该都能懂
$scope.$watch(function ngmodelwatch() { //解析ngmodel的表达式,获取内容 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? //判断表达式的值是否跟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); } } //返回解析的表达式 return modelvalue; }); }];
以上就是小编为大家带来的浅谈angular中ngmodel的$render全部内容了,希望大家多多支持~