浅谈Angular中ngModel的$render

 更新时间:2016年10月24日 09:56:21   投稿:jingxian  
下面小编就为大家带来一篇浅谈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全部内容了,希望大家多多支持脚本之家~

相关文章

  • angular2使用简单介绍

    angular2使用简单介绍

    Angular2开发者预览版出来已有一段时间,这个以速度与移动性能为目的的框架到底如何,今天我们来结合官网的demo尝试一下。
    2016-03-03
  • Angular学习笔记之angular的$filter服务浅析

    Angular学习笔记之angular的$filter服务浅析

    本文是小编记录的angular学习笔记,通过本文首先给大家介绍了$filter服务,然后介绍下内置filter及filter的简单使用,非常不错具有参考借鉴价值,感兴趣的朋友一起看看吧
    2016-11-11
  • AngularJS的内置过滤器详解

    AngularJS的内置过滤器详解

    在我们开发中经常需要在页面显示给用户的信息需要一定处理格式化,才能显示给用户。在angularjs中为我们提供了叫filter的指令,让我们能够很轻易就能做到着一些列的功能,angularjs内部为我们提供了number等很多内置的filter。
    2015-05-05
  • 对angularJs中$sce服务安全显示html文本的实例

    对angularJs中$sce服务安全显示html文本的实例

    今天小编就为大家分享一篇对angularJs中$sce服务安全显示html文本的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-09-09
  • AngularJs concepts详解及示例代码

    AngularJs concepts详解及示例代码

    本文主要介绍AngularJs concepts,这里整理了详细资料及简单示例代码来讲解相关知识,有学习这部分知识的朋友可以参考下
    2016-09-09
  • 移除AngularJS下URL中的#字符的方法

    移除AngularJS下URL中的#字符的方法

    这篇文章主要介绍了移除AngularJS下URL中的#字符的方法,AngularJS是一款高人气JavaScript库,需要的朋友可以参考下
    2015-06-06
  • 使用AngularJS实现可伸缩的页面切换的方法

    使用AngularJS实现可伸缩的页面切换的方法

    这篇文章主要介绍了使用AngularJS实现可伸缩的页面切换的方法,AngularJS是一款热门的JavaScript库,需要的朋友可以参考下
    2015-06-06
  • Angular 4.x 路由快速入门学习

    Angular 4.x 路由快速入门学习

    这篇文章主要介绍了Angular 4.x 路由快速入门学习,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-05-05
  • 对angularJs中自定义指令replace的属性详解

    对angularJs中自定义指令replace的属性详解

    今天小编就为大家分享一篇对angularJs中自定义指令replace的属性详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-10-10
  • 浅谈angular2子组件的事件传递(任意组件事件传递)

    浅谈angular2子组件的事件传递(任意组件事件传递)

    今天小编就为大家分享一篇浅谈angular2子组件的事件传递(任意组件事件传递),具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-09-09

最新评论