angular中指令被用的最多的除了ng-repeat之外就非他莫属了吧,由于各种业务的需求,我们经常需要去写一些继承ngModel的指令,来满足各种奇葩需求,最多的莫过于表单的验证啦,另外你在封装一些jquery插件的时候,也是需要继承ngModel的,最典型的莫过于 datepicker、fileUpload等等。

  但是ngModel本身其实有很多坑,在这里分享给大家,如果大家又遇到其他问题,欢迎补充:

  首先我们要知道一些概念的东西,这里我就不占篇幅了,不了解的可以先去看看这篇文章:

    http://www.cnblogs.com/liulangmao/p/4110137.html  

  在这里,我基本分为两种问题,一种是viewValue和modelValue不同的问题,另一种是管道问题

    第一种:viewValue和modelValue不同的问题

      1.viewValue想变成modelValue

      2.modelValue想变成ViewValue        

      3.moduleValue想和viewModel不一样

      4.viewModel和DOM元素的值不一样

      要想解决这些问题,我们先来了解一些$apply的一个问题,那就是执行$apply之后数据是以什么为主的

      ①viewValue -> modelValue

      ②modelValue -> viewValue,于是我们写了下面这个指令      

 <input type="text" ng-model="vm.modelTest" model-test>  
.directive('modelTest',function(){
return {
require : 'ngModel',
link : function(scope,iElm,iAttrs,ngModelCtrl){
iElm.on('mouseenter',function(){
console.info("打印出更改之后,没有执行$apply的值")
console.log(ngModelCtrl); //更改modelValue的值
ngModelCtrl.$modelValue = "test change"; console.info("打印出更改之后,没有执行$apply的值")
console.log(ngModelCtrl); //执行$apply
scope.$apply(); console.info("打印出更改之后,执行$apply的值")
console.log(ngModelCtrl);
})
}
}
})

    从上面的指令,我们不难得出一个比较武断的结论 $apply会根据viewValue的值而改变modelValue的值,也就是modelValue -> viewValue,那么,我们可以开始解决我们的问题了。    

      1.viewValue想变成modelValue

        这种情况很少, 但是如果你在jq的操作就可能发生这种需求,一般依然还是$apply让model的值重新更新,使用了$apply就会触发$render()函数,因为modelValue的变化,会导致$render触发

      2.modelValue想变成ViewValue (看了上面的实验,我想你应该懂了,直接使用$apply)       

      3.moduleValue想和viewModel不一样

        一般情况都会使用管道去解决,但是有个其他思路可以提供给大家,下面这段代码是在国外看到的,觉得挺不错的,效果大家可以去尝试下,将model的值变成数组。

ngModelCtrl.$viewChangeListeners.push(function(){
$parse(iAttrs.ngModel).assign(scope, ngModelCtrl.$viewValue.split(','));
});

    第二种:管道问题

      管道是什么呢,在ngModel里面其实就是view视图和model视图数据交互的时候需要经过的数组或对象,这个数组或对象由方法组成,每次经过都会执行数组里面的方法,并返回结果。一共有四种管道

      $formatters :它是model视图转向view视图的管道(数组),model的值会经过他才转变成view视图的值,另外它的调用顺序是最特别的,从后往前调用,,越在数组后面,越早调用。

      $parsers : 它正好是跟$formatters相反,是view视图转向model视图的管道(数组),view的值会经过他才转变成model视图的值,在1.2.x(兼容IE8)之前一般我们会在这里实现或扩展验证功能

      $validators:这是在1.3.x之后出现的管道(json对象),来帮助我们实现和扩展验证功能的,当我们进入$parsers的同时,同时也会进入$validators,在这里我贴段源码(验证required)给大家看看,我想大家应该能理解这个管道的功能

ctrl.$validators.required = function(modelValue, viewValue) {
return !attr.required || !ctrl.$isEmpty(viewValue);
};

      $asyncValidators :功能与$validators相似,不同的是他可以实现异步验证,你可以在管道内部执行异步处理,会在结果返回之后,才去设置验证结果,这是个大课题,我看到有人讨论过,我也就不详细讲了http://www.cnblogs.com/liulangmao/p/4118868.html可以进去这个博客看看。

      好了,ngModel的一些东西基本已将讲完了,另外还有一些就不仔细去说了,我的博客里面还有一篇关于$render的详解,有兴趣的可以了解下。

      此帖是原创,转载请注明

angularJs中ngModel的坑的更多相关文章

  1. AngularJs 中ngModel绑定HTML5 date数据同步问题

    以下代码例子中,直接将date类型的input标签与ng-model对应的变量绑定,会出现内存数据和页面数据不一致的问题.虽然AngularJS是双向数据绑定,但是如果用下面的方法,在页面更新date ...

  2. AngularJS 中ng-model通过$watch动态取值

    这个例子的意思是,当xxxx的长度不超过6时,xxxx和yyyy两个input的model是无关的,但当xxxx超过6,则yyyy会跟随其值而变化. 另一种做法是在input的ng-model后面添加 ...

  3. AngularJS移动开发中的各种坑

    捂脸,辛酸泪ing...... 本文主要涉及部分在移动设备上特有的问题. 相对来说,Jquery侧重DOM操作,AngularJS是以视图模型和双向绑定为核心的. DOM操作的问题 避免使用 jQue ...

  4. AngularJS 中的作用域

    问题引入 使用 Angular 进行过一段时间的开发后,基本上都会遇到一个这样的坑: 123456789101112 <div ng-controller="TestCtrl" ...

  5. 深入学习AngularJS中数据的双向绑定机制

    来自:http://www.jb51.net/article/80454.htm Angular JS (Angular.JS) 是一组用来开发Web页面的框架.模板以及数据绑定和丰富UI组件.它支持 ...

  6. AngularJS中的表单验证

    AngularJS中的表单验证 AngularJS自带了很多验证,什么必填,最大长度,最小长度...,这里记录几个有用的正则式验证 1.使用angularjs的表单验证 正则式验证 只需要配置一个正则 ...

  7. angularjs中的directive scope配置

    angularjs中的directive scope配置 定义directive其中重要的一环就是定义scope,scope有三种形式: 默认的scope,DOM元素上原有的scope scope: ...

  8. AngularJS中的指令全面解析(转载)

    说到AngularJS,我们首先想到的大概也就是双向数据绑定和指令系统了,这两者也是AngularJS中最为吸引人的地方.双向数据绑定呢,感觉没什么好说的,那么今天我们就来简单的讨论下AngularJ ...

  9. angularJS中directive与controller之间的通信

    当我们在angularJS中自定义了directive之后需要和controller进行通讯的时候,是怎么样进行通讯呢? 这里介绍3种angular自定义directive与controller通信的 ...

随机推荐

  1. .net core 读取配置文件

    /// <summary> /// 读取配置信息 /// </summary> public class Zconfig { #region 读取配置信息 /// <su ...

  2. SQLServer 错误: 15404,无法获取有关 Windows NT 组 用户

    因做服务器数据库迁移,造成的一系列问题, 1.重启SQL 代理,操作也不可. 然后又进行操作: SQL---------安全性------登录名 中原来的系统用户名前的计算机名更改为现在所用的计算机名 ...

  3. linux手工笔记

    一.vi编辑器常用命令: -------------------------------- •插入文字:I键A键 •退回命令模式:ESC •存盘:w •不存盘退出:q •存盘退出:wq •强制退出:q ...

  4. C++ 中 const和define的区别

    来源网址:http://wujiangping.blog.163.com/blog/static/195182011201255115125205/ 请区别用#define命令定义的符号常量和用con ...

  5. JSP内置对象--pageContent,request,response,session,application,config,out,page,exception

  6. 杂音 & pop 音的解决方法

    杂音 & pop 音的解决方法 1. 喇叭有严重的"吱吱"破音,绝大多数的原因有可能在于V(out)电压不稳定,所以最好测一下无负载时的输出电压.同时也可以测量 VCC – ...

  7. MULE-ET0 、 ET1、ET2、PT1、PT2

    设计验证阶段中的五个样车试制概念 骡子车( mule car ) ET0 第一轮设计工程样车试制 ET1 第二轮设计工程样车试制 ET2 第一轮产品工装样车试制 PT1 第二轮产品工装样车试制 PT2 ...

  8. Windows平台查看端口占用情况

    1.查看所有的端口占用情况 netstat -ano 协议    本地地址                     外部地址               状态                   PI ...

  9. centos mono

    wget http://download.mono-project.com/sources/mono/mono-4.0.1.tar.bz2wget http://download.mono-proje ...

  10. redis采用序列化方案存对象

    前几天被问到这样一个问题,redis怎么存对象,平时也没怎么注意,只知道redis存字符之类的,不过就是根据键存取值,不过对象的话还是不同的 首先来了解一下为什么要实现序列化 为什么要实现序列化接口 ...