浅谈Angular中ngModel的$render


Posted in Javascript onOctober 24, 2016

在我开始着手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);
        }) 
      }
    }
  })

我们分几种情况分析

这是鼠标没有经过指令的时候的样子

浅谈Angular中ngModel的$render

1.当我们使用js原生方法设置input的val值的时候,并且不执行$render函数,我们可以看到input里面的model值是没有变化的,但是input的的value是变成了1,而且我们看到不仅model值没有变化,ngModel的$viewValue和$modelValue同样也没有变化。我们可以得出结论 (input的value值不一定等于$viewValue)

结果是这样的

浅谈Angular中ngModel的$render

--------------------------------------------------------------------------

然后,我们尝试在执行js原生改变value值之后,执行$render函数是个什么样的状况,

浅谈Angular中ngModel的$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是不同的)

浅谈Angular中ngModel的$render

现在我们在$setViewValue之后使用,$render()看看是什么效果,

浅谈Angular中ngModel的$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全部内容了,希望大家多多支持三水点靠木~

Javascript 相关文章推荐
javascript 写类方式之十
Jul 05 Javascript
基于jquery的弹出提示框始终处于窗口的居中位置(类似于alert弹出框的效果)
Sep 28 Javascript
form表单中去掉默认的enter键提交并绑定js方法实现代码
Apr 01 Javascript
js网页版计算器的简单实现
Jul 02 Javascript
JavaScript实现向setTimeout执行代码传递参数的方法
Apr 16 Javascript
JS+CSS实现闪烁字体效果代码
Apr 05 Javascript
jQuery实现链接的title快速出现的方法
Feb 20 Javascript
Vue2.0表单校验组件vee-validate的使用详解
May 02 Javascript
mpvue微信小程序多列选择器用法之省份城市选择的实现
Mar 07 Javascript
js实现unicode码字符串与utf8字节数据互转详解
Mar 21 Javascript
JavaScript从原型到原型链深入理解
Jun 03 Javascript
在vue中使用防抖函数组件操作
Jul 26 Javascript
Javascript vue.js表格分页,ajax异步加载数据
Oct 24 #Javascript
H5移动端适配 Flexible方案
Oct 24 #Javascript
javascript的document中的动态添加标签实现方法
Oct 24 #Javascript
Ajax+FormData+javascript实现无刷新表单信息提交
Oct 24 #Javascript
利用JS实现点击按钮后图片自动切换的简单方法
Oct 24 #Javascript
express文件上传中间件Multer详解
Oct 24 #Javascript
用js实现博客打赏功能
Oct 24 #Javascript
You might like
dedecms防止FCK乱格式化你的代码的修改方法
2007/03/17 PHP
PHP的PSR规范中文版
2013/09/28 PHP
WordPress迁移时一些常见问题的解决方法整理
2015/11/24 PHP
什么是PHP文件?如何打开PHP文件?
2017/06/27 PHP
Laravel源码解析之路由的使用和示例详解
2018/09/27 PHP
JavaScript 存在陷阱 删除某一区域所有节点
2010/05/10 Javascript
JS+flash实现chrome和ie浏览器下同时可以复制粘贴
2013/09/22 Javascript
初识Node.js
2014/09/03 Javascript
浅析AngularJS中的指令
2016/03/20 Javascript
Javascript获取background属性中url的值
2016/10/17 Javascript
微信 java 实现js-sdk 图片上传下载完整流程
2016/10/21 Javascript
微信小程序 toast 详解及实例代码
2016/11/09 Javascript
easyUI实现类似搜索框关键词自动提示功能示例代码
2016/12/27 Javascript
node.js实现复制文本到剪切板的功能
2017/01/23 Javascript
如何理解jQuery中的ajaxSubmit方法
2017/03/13 Javascript
浅析JavaScript中的平稳退化(graceful degradation)
2017/07/24 Javascript
jQuery实现的鼠标滚轮控制图片缩放功能实例
2017/10/14 jQuery
JS实现定时任务每隔N秒请求后台setInterval定时和ajax请求问题
2017/10/15 Javascript
bootstrap select下拉搜索插件使用方法详解
2017/11/23 Javascript
vue编译打包本地查看index文件的方法
2018/02/23 Javascript
[06:06]2018DOTA2亚洲邀请赛主赛事第四日战况回顾 全明星赛欢乐上演
2018/04/07 DOTA
在Python中使用正则表达式的方法
2015/08/13 Python
Python基于回溯法子集树模板解决旅行商问题(TSP)实例
2017/09/05 Python
python中yaml配置文件模块的使用详解
2018/04/27 Python
python自动查询12306余票并发送邮箱提醒脚本
2018/05/21 Python
Python实现12306火车票抢票系统
2019/07/04 Python
Python Django框架url反向解析实现动态生成对应的url链接示例
2019/10/18 Python
Pytest框架之fixture的详细使用教程
2020/04/07 Python
用Python进行websocket接口测试
2020/10/16 Python
html5中去掉input type date默认样式的方法
2018/09/06 HTML / CSS
成考报名单位证明范本
2014/01/16 职场文书
乡下人家教学反思
2014/02/01 职场文书
原材料检验岗位职责
2014/03/15 职场文书
课堂打架检讨书200字
2014/11/21 职场文书
应届生简历自我评价
2015/03/11 职场文书
初中英语教学反思范文
2016/02/15 职场文书