资讯专栏INFORMATION COLUMN

Angular1.x中ngModel的$render的详解

Euphoria / 363人阅读

摘要:我们下面来看看的源码这是其中一个,在不同的指令下的代码都不太一样,但是其作用基本一致,但是从这里我们就可以看出的到底在干什么事了。

这篇文章是我两年前在博客园写的,现在移植过来,不过Angular 1.x 在国内用的人已经不多了,希望能帮助到有需要的人

在我开始着手 ngModel 的领域时候,有一个问题很令我纠结,那就是 $render 到底是做什么的呢?查了很多资料都只是简单的描述一下,这就令我很纠结了,终于在一个阳光明媚的晚上,我终于解决了这个大问题

那么这个 $render 方法到底是干什么的呢?他的用处就是在 $viewValue 改变的时候可以重新绑定 model 数据,但是我们要注意一点( $viewValue 和 DOM 节点的 value 是不同的),我觉得他们的区别有点类似 setTimeout$timeout 的区别,但是又不太一样。PS:其实 modelValue 和绑定的数据也可以不同

Input里面模型的值:{{vm.modelTest}}

.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 执行事件的源代码在这里,里面我写了注释,大家应该都能懂,好了,$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;
});

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/92914.html

相关文章

  • ngModel使用说明小demo

    摘要:关于个管道的用法会在下一篇里面讲。一般需要通过去调用方法去时和上挂载的属性值保持一致。方法是可以重新自定义的上的属性值,已经发生变化利用这些值再次可以再次做相应的处理,然后更新抽时间把关于再补上。参考资料指令中使用中的的详解 第一个点,要了解下: DOM value $viewValue $modelValue scope上挂载的属性的值 一般有2个流程: $vie...

    zorro 评论0 收藏0
  • Angular 2 快速上手

    摘要:为了简单起见,在本文中将会使用。已经实例化了并且将它的模板载入到了元素中。中的依赖注入发生在该类的构造函数中,因此我们将在构造函数中注入。 国内 Angular2 资料比较少,这里看到一篇不错的入门文章就分享过来了 —— Angular 2 快速上手,这里面还有很多有关于 Angular2 的文章,感兴趣的朋友可以去看一看 目前angular2已经来到了beta版,这意味着它已经做好了...

    singerye 评论0 收藏0
  • angular1.x和angular2+并行,angular1.x 升级 angular2+方案

    摘要:可以在不必打断其它业务的前提下,升级应用程序,因为这项工作可以多人协作完成,在一段时间内逐渐铺开,下面就方案展开说明主要依赖提供模块。在混合式应用中,我们同时运行了两个版本的。这意味着我们至少需要和各提供一个模块。 angular1.x 升级 angular2+ 方案 我给大家提供的是angular1.x和angular5并行,增量式升级方案,这样大家可以循序渐进升级自己的应用,不想看...

    Olivia 评论0 收藏0
  • angular1学习笔记,view model 同步过程

    摘要:但实际上这时程序并没有计算手续费。经过排查并查阅文档之后,发现是的问题。本文没有具体介绍和管道,关于这部分可以参考文中给出的链接 事情起源于在项目中遇到的一个小问题:项目中需要一个输入框输入卖出产品数量,并且在用户输入后根据输入数据计算手续费。很自然的我用了ng-model和ng-change,并且一般情况下没什么问题。问题是:输入框下还有一个按钮是全部卖出,点击这个按钮程序会自动设置...

    Forelax 评论0 收藏0
  • webpack+es6+angular1.x项目构建

    摘要:技术栈概述大名,顾名思义是在年月正式发布的一套标准。小名,意为第六次变更。本项目,选择的是的推荐配置,唯一注意的是全局变量中把的关键词加上。项目结构公共组件目录,放一些二次封装的等等片段式的。项目的公用样式目录。 技术栈概述 ES2015(ES6) 大名ES2015,顾名思义是 ECMAScript 在2015年6月正式发布的一套标准。小名ES6,意为ECMAScript第六次变更。(...

    KoreyLee 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<