angular指令心得(ng-model)

在项目中编写指令,常常会依赖其他的指令来实现想要达到的功能,其中最常用到的便是ng-model,它为我们明确了需要绑定的属性,虽然在指令中可以通过通过使用独立作用域的”=”来进行双向绑定,但使用ng-model更能简化指令的传值,符合angular的使用习惯。


指令依赖

angular中编写自定义指令是通过require属性来指定查找依赖指令的controller,并传入link函数中进行调用.

.directive("...",function(){return {...require:'ngModel',link:function(scope,elem,attr,ngModelCtr){...}...}
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

所依赖指令的控制器被传入link的第四个参数中,可以依赖多个指令,此时第四个参数则是个数组。

.directive("...",function(){return {...require:['ngModel','^?form',...],link:function(scope,elem,attr,ctrls){...}...}
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

在查找指令的过程中,如果未找到指令,则会抛出一个编译错误。 
可以通过加前缀来控制其查找的操作。

前缀 作用
^ 向上查找指令,未找到则报错。
? 未找到,取消报错,将null传到link的第四个参数。

ng-model

使用ng-model前,让我们先简单了解一下ng-model的工作原理。

angular是一个mvvm的框架,其主要就体现在ng-model身上 
 
angular将model和view之间的联系切断,自己内部通过ng-model去实现ViewModel层,具体的细节不表,我们就看下我们要用的部分。

在每个使用ng-model的地方,都会创建一个ngModelController实例,这个实例负责管理存储在模型(由model指定)中的值与元素显示值之间的数据绑定。

ngModelController包含有$formatters和$parsers数组,会在每次更新数据绑定是调用。

当我们从页面或通过$setViewValue改变绑定的属性时,会遍历执行$parsers数组里面的方法,而当我们直接在js里面通过赋值语句修改时,则会调用$formatters数组。

// line number:25332
// model -> value// Note: we cannot use a normal scope.$watch as we want to detect the following:// 1. scope value is 'a'// 2. user enters 'b'// 3. ng-change kicks in and reverts scope value to 'a'//    -> scope value did not change since the last digest as//       ng-change executes in apply phase// 4. view should be changed back to 'a'$scope.$watch(function ngModelWatch() {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?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)) {ctrl.$modelValue = ctrl.$$rawModelValue = modelValue;parserValid = undefined;var formatters = ctrl.$formatters,idx = formatters.length;var viewValue = modelValue;while (idx--) {viewValue = formatters[idx](viewValue);}if (ctrl.$viewValue !== viewValue) {ctrl.$viewValue = ctrl.$$lastCommittedViewValue = viewValue;ctrl.$render();ctrl.$$runValidators(modelValue, viewValue, noop);}}return modelValue;});
}];
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

上面是angular调用$formatters的地方,它监控了model值的变化,负责model->view。


实践

<html lang="en" ><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><title>angular-ngModel-test</title><script type="text/javascript" src="http://cdn.bootcss.com/angular.js/1.5.0-beta.1/angular.js"></script><script type="text/javascript">angular.module("testModule",[]).controller("testCtr",function($scope){}).directive("testDire",function(){return {restrict:"A",require:"ngModel",link:function(scope,elem,attr,ngModelCtr){}}}) </script>
</head><body ng-app="testModule" ng-controller="testCtr"><input type="text" test-dire ng-model="say"/><h1>{{say}}</h1></body></html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

$formatters & $parsers


$formatters

上面搭建了一个基本的架子,现在我们通过来通过js改变模型值,在$formatters里面加入一个格式化方法来显示到页面上。

改动:

<!-- html -->
<body ng-app="testModule" ng-controller="testCtr"><input type="text" test-dire ng-model="say"/><button ng-click="joke()">窗前明月光</button><h1>{{say}}</h1
</body>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
//js
.directive("testDire",function(){return {restrict:"A",require:"ngModel",link:function(scope,elem,attr,ngModelCtr){ngModelCtr.$formatters.push(function(modelValue){if(typeof modelValue != "undefined"){//返回字符串给view,不改变模型值return "李白睡的香"; }})}}
}) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

效果图: 

这里有个很奇怪的现象,两个绑定model的地方显示的值不一样,这是因为input是从ngModelController中获得的返回值显示出来的,这个值在通过$formatters数组时被我拦截下来,返回了另外一个字符串。


$parsers

我们还可以对界面(view)输入后的值进行处理。

改动:

//js
.directive("testDire",function(){return {restrict:"A",require:"ngModel",link:function(scope,elem,attr,ngModelCtr){...ngModelCtr.$parsers.push(function(viewValue){if(typeof viewValue != "undefined"){return "我说:"+viewValue;}})}}
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

效果图: 


$render & $setViewValue


$render

有的时候,$formatters数组里面也许会有不止一个方法,这时候为了保证一个最终的显示效果,就应该用到$render方法。 
TIP:$render总会在$formatters完成之后调用。

重新赋值$render方法,在改变模型值后修改字体颜色。

改动:

//js
.directive("testDire",function(){return {restrict:"A",require:"ngModel",link:function(scope,elem,attr,ngModelCtr){...var h1Elem = document.getElementsByTagName("h1")[0];ngModelCtr.$render = function(){if(typeof scope.say != "undefined"){h1Elem.style.color = "red";}}}}
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

效果图: 

结果可以看到,颜色成功改变了,但是输入框没有变化。 
造成这个的原因是因为我们重写了$render方法,相当于改写了ng-model从model到view的dom操作,用自己的方式去实现。


$setViewValue

的作用是为了在指令中改变ng-model绑定的值,适用于使用了独立作用域的指令(在没有双向绑定属性的情况下,无法通过scope进行赋值)。

下面在加载自执行的时候通过指令改变模型值。

改动:

//js.directive("testDire",function(){return {restrict:"A",require:"ngModel",link:function(scope,elem,attr,ngModelCtr){...ngModelCtr.$setViewValue("hello");}}
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

效果图: 


总结

在指令中,我们可以用通过简单的依赖ng-model去实现angular各种其他插件的兼容(如一些日期控件,富文本编辑器等),更能简化我们的指令代码,避免很多复杂的绑定逻辑,特别要注意的是$formatters,$passers,$render这些都会在初始化时去执行一遍,因此应该根据需要做好判断操

转http://blog.csdn.net/qq_17371033/article/details/49248791

angular指令心得(ng-model)相关推荐

  1. 使用Angular cli(ng generate)创建组件、服务、类、路由、指令、管道

    日常angular开发中,相信不少人在创建新组件时,普遍会采用复制粘贴的方式创建新的组件或服务等.其实可以采用ng generate的方式快速创建组件.服务.类.路由等. 在使用angular cli ...

  2. angular项目 集成ng zorro 和ng alain

    angular项目 集成 ng zorro和ng alain(mock 和acl权限)学习笔记 这段时间,比较忙,很久没有写博客了.作为后端开发人员,第一次接触angular,以下是个人的学习心得和D ...

  3. Angular指令渗透式理解

    通过一段时间对angular指令的使用,理解了angular指令的意义,下面逐一介绍一下. ng-app:定义一个angualr模块,表示angular作用的范围,如下代码: ng-app在html标 ...

  4. Angular指令 - 何时以及如何使用编译,控制器,预链接和后链接[关闭]

    本文翻译自:Angular directives - when and how to use compile, controller, pre-link and post-link [closed] ...

  5. angular指令:tm.tags添加/删除标签

    一个添加删除标签angular指令: 在网上找了几个标签插件都不是angular的,而且过于庞大,最小的也要30kb还引用了其他样式. 最后实在受不了自己写了,花4个小时找插件,最后自己2小时写完了. ...

  6. angular 指令

    Angular 指令的不同类型如下: 组件 -- 带有模板的指令.这种指令类型是最常见的指令类型. 属性型指令 -- 更改元素.组件或其他指令的外观或行为的指令. 结构型指令 -- 通过添加和删除 D ...

  7. Angular CLI 全局 ng.cmd 文件内容分析

    文件内容如下: REM Jerry ::这是注释 @ECHO off SETLOCAL CALL :find_dp0IF EXIST "%dp0%\node.exe" (SET & ...

  8. html input ng model,Angular自定义指令中传递ngModel

    根据项目需要,希望写一个自定义指令,将指令中传递的数据(比如:my-model="name"),绑定到template中的ng-model中,并且可以被外部作用域使用. 参考了&l ...

  9. angular(使用Angular指令)

    一.设计模式 所谓的设计模式就是一套被反复使用的,多数人知道的,经过分类编写的,代码设计经验的总结,使用设计模式可以提高代码的重用性和可读性. 1.设计模式分类 单例模式.代理模式.观察者模式.MVC ...

最新文章

  1. python程序不出结果_超详细的Python入门教程,1小时就可以学会
  2. QIIME 2教程. 08差异丰度分析gneiss(2021.2)
  3. BZOJ[1713][Usaco2007 China]The Bovine Accordion and Banjo Orchestra 音乐会 二维斜率优化
  4. 聚类算法当中的K-means算法如何去做天猫淘宝的推广任务
  5. Bootstrap-datetimepicker控件使用
  6. python actor_Python定义一个Actor任务
  7. 关闭Visual Studio 实时调试器
  8. .NET2.0中,Winform程序如何异步调用Web Service呢?[Demo下载]——与.net1.1环境下比较...
  9. c# pdf转html,C# 将PDF转为Word、Html、XPS、SVG、PCL、PS——基于Spire.Cloud.PDF
  10. 电感电容之开关电源的原理
  11. 网站建设公司该不该把web前端外包出来!精辟
  12. html移动轮播后盾网,后盾网lavarel视频项目---Vue项目使用vue-awesome-swiper轮播插件...
  13. Chrome中devtools安装
  14. 关闭Nao机器人自带的摔倒保护
  15. GIS操作之高程、坡度、坡向
  16. 〖产品思维训练白宝书 - 核心竞争力篇⑪〗- 产品经理核心竞争力解读之管理能力
  17. rtf格式的一些说明
  18. 工资4500,副业22000,淘宝赚钱的路子到底有多野????
  19. 如何打开7z格式的压缩文件?
  20. 歌谣学前端之解构赋值

热门文章

  1. 嵌入式Linux中摄像头使用简要整理
  2. win10系统MongoDB 4.0安装配置记录
  3. 基于matlab的优化设计,基于MATLAB的Wilson方法的叶片优化设计.pdf
  4. 青山依旧在,2021这一年
  5. 图片隐写查看神器stegsolve使用方法
  6. 网页右下角弹出提示框
  7. indesign选中不了图片删除_有办法了!批量删除多个Word页眉页脚
  8. ubuntu下 gcc工具链的安装
  9. 建筑市场监管平台解密
  10. Android手机传感器的使用