angular 指令 要点解析
指令可以删繁就简前端的js代码,杜绝重复的js代码和html代码。
下面就对指令的重要属性进行罗列
一、restrict 定义指令的出现形式
可以定义为多种形式,比如 restrict = 'AE' 标识可以是属性,也可以是元素。restrict = 'AECM' 则标识支持下面所有形式
- Attribute 属性: <div my-directive=”exp”></div>
- Element 元素: <my-directive></my-directive>
- Class : <div class=”my-directive:exp;”></div>
- M 注释:<!-- directive: my-directive exp -->
鉴于浏览器兼容问题。推荐 restrict = 'A'
二、scope 作用域,与值绑定
scope = true/false/{name:'=/@/&'}
默认为false,如果设置为true 则说明指令内部独立作用域。
scope: {
lover: '=',
name: '@',
say: '&'
}
1、{name:'@inputName'} name 指 指令中作用域中scope.name , inputName 可不写。默认绑定属性name。eg:<directive inputName="小明-{{data.class}}">
2、= 双向绑定比较常用
如:<lover="绑定内容"> 绑定内容可以理解为指令外部scope环境中的所有。它已经不是字符串的意义。甚至比如一个function的引用。 lover="sayChange" 那么love()就执行scope.sayChange(),如果scope.sayChange是对象、那么lover改变与sayChange改变均会联动修改关联的对方。
3、”&“:绑定 Contoller中对应$scope上的函数。
三、template/templateUrl
模板,该指令内部会被改html所代替, 如果设置了replace =true ,则outerHtml也会被移除。(会影响改标签后面的其他指令)
四、combine编译阶段 提供两个参数element,attrs。
可以对当前元素做一些操作。返回link方法或者什么prelink等等。细节不说了。感觉用的也不多。 此处存在一个小bug 这个阶段给element添加进去的html包含{{}} 到后面不会执行。但是加上 template=“”,就可以解决
五、link 参数为 scope ,element,attrs ,ctrl ( ctrl 当 require = ngController才会有)
如果有combine,link需要作为combine的return 对象。
link require="ngModel",则可以拿到ngModelController,那么Ctrl就可以有很多的扩展点,这也是我要写本文的目的所在。其他事不过走走过场而已。
ngModel对于值有两个重要的概念叫modelValue,和viewValue 见名知意,我们可以理解为数据库持久化值为ModelValue而最终展示到UI上给用户看到的是viewValue。他们可以不同。
1、ctrl.$formatters 格式化链 ngModel 的 ModelValue to ViewVlaue过程中需要有序执行的一串 function,
那就太方便了。比如扩展格式化:日期、金额格式化;校验:假如modelValue不合法、则不会展示到前端。
2、 ctrl.$parsers 解析链 ngModel 的 ViewValue to ModelValue过程中需要执行的一串function
同样在 反格式化的处理:金额去除¥符号转为数字;校验不合法的数据无法提交给ModelView,(不提交给ModelValue 其他对改字段监控变化就不会得到通知。 angular双向绑定多么美妙的设计,)
3、ctrl.$render 当视图需要更新时执行。
比如checkbox viewValue改成了false,render会将原生checkbox 的checked=true,可以重新赋值修改该function
最后提供几个例子可以感受formatters ,parsers ,强大的扩展性。
1 /** 2 * @ht-boolean 可为空, 格式以“/”分割truevalue 和falsevalue 3 * <span ht-boolean="Y/N" text="测试按钮" ng-model="prop.skipFirstNode" ht-tip title="我是按钮的提示"/> 4 */ 5 .directive('htBoolean', function() { 6 return { 7 restrict : 'A', 8 require:'ngModel', 9 scope : true, 10 link : function(scope, element, attrs,ctrl) { 11 var booleanConf =attrs.htBoolean; 12 scope.text = attrs.text; 13 if(booleanConf) booleanConf=booleanConf.split("/"); 14 else booleanConf = [true,false]; 15 16 var trueValue = booleanConf[0],falseValue = booleanConf[1]; 17 18 ctrl.$formatters.push(function(value){ 19 return value === trueValue; 20 }); 21 22 ctrl.$parsers.push(function(value){ 23 return value ? trueValue : falseValue; 24 }); 25 26 ctrl.$render = function(){ 27 scope.checked = ctrl.$viewValue; 28 }; 29 30 element.on('click', function(){ 31 scope.$apply(function() { 32 scope.checked = !scope.checked; 33 ctrl.$setViewValue(scope.checked); 34 }); 35 }); 36 }, 37 template:'<lable class="btn label-sm {{checked ? \'active\':\'inactive\'}}" >{{text}}</lable>' 38 }; 39 })
自定义表单校验 扩展平台自有校验
六、controller($scope,element)
最后推荐有些异常情况无法解决的同仁直接查看源码,angular.js @license AngularJS v1.2.19
compileNodes 便是编译DOM元素的方法,里面applyDirectivesToNode 为实际处理指令的方法。 跟一下相信就清楚了。