指令 Directive
指令系统(Directive)是Angular应用的一个重要特性。
是通过对DOM元素的标签丶属性来增强HTML表现力,为其增加一些特定功能。
本篇参考文档Angular菜鸟教程
内置指令
这里介绍的是常用的一些angularJs内置指令:
1、ng-model
这个是将表单控件和当前作用域的属性进行绑定。需要注意绑定的scope的范围(父scope与子scope)。
ng-model主要绑定的元素包括input, select, textarea 。
ng-model的元素都有:
ng-valid(可用),
ng-invalid (不可用)
ng-pristine(用户为对这个元素进行操作过),
ng-dirty(元素的模型发生改变的话)属性; 这几个属性都是布尔值。
2、ng-init
该指令被调用时会初始化内部作用域。一般不建议使用此参数。
3、ng-app
用于告诉 AngularJS 应用当前这个元素是根元素。
所有 AngularJS 应用都必须要要一个根元素。
HTML 文档中只允许有一个 ng-app 指令,如果有多个 ng-app 指令,则只有第一个会被使用。
下边是关于ng-app需要注意的点:
1>这个是必需的。使用该指令自动启动一个AngularJS应用。
2>ngapp指令指定的应用程序的根元素,通常放置在网页的根元素如body或html 标签。
3>只有一个AngularJS应用可以自动引导每个HTML文档。
4.第一ngapp找到该文件将定义自动引导的根元素的应用。
5>运行多个应用程序在一个HTML文件,您必须手动引导他们使用angular.bootstrap。
6>AngularJS应用不能互相嵌套。
7>你可以指定一个AngularJS模块被用于应用程序的根模块。
8>该模块将被加载到应用程序时,引导到$injector对象中。
9>它应该包含所需的应用程序代码,或依赖于将包含代码的其他模块的依赖关系。
4、ng-controller
用于为你的应用添加控制器。
<element ng-controller="expression"></element>//expression 控制器名。
在控制器中,你可以编写代码,制作函数和变量,并使用 scope 对象来访问。
5、ng-form
Angular表单其实是Angular提供的Directive,它有一个别名叫ng-form。是这个Directive实例化了一个FormController来负责表单内的页面逻辑(主要是表单验证)。
6、ng-disabled
设置表单输入字段的 disabled 属性(input, select, 或 textarea)。
如果 ng-disabled 中的表达式返回 true 则表单字段将被禁用。
我们可以在AngularJS中通过表达式返回值true/false令其生效。
<input ng-disabled="expression"></input>//expression 如果表达式返回true,则设置为元素添加 disabled 属性。
7、ng-readonly
设置表单输入字段设为只读。
可以通过表达式返回值true/false将表单输入字段设为只读。
8、ng-checked
设置是否选中复选框。
其中 ng-true-value="''" ng-false-value="''",可用来设置选中时或不选中时对应的值
9、ng-selected
用于设置 <select> 列表中的 <option> 元素的 selected 属性。
ng-selected 属性的表达式返回 true 则选项被选中。
10、ng-show/ng-hide
根据表达式显示/隐藏HTML元素,注意是隐藏,不是从DOM移除(ng-if才是移除)
对于大对象的DOM,可以用它,但如果是小对象的DOM,建议使用ng-if
11、ng-change
ng-change 指令用于告诉 AngularJS 在 HTML 元素值改变时需要执行的操作。
ng-change 指令需要搭配 ng-model 指令使用。
AngularJS ng-change 指令指令不会覆盖原生的 onchange 事件, 如果触发该事件,ng-change 表达式与原生的 onchange 事件都会执行。
ng-change 事件在值的每次改变时触发,它不需要等待一个完成的修改过程,或等待失去焦点的动作。
ng-change 事件只针对输入框值的真实修改,而不是通过 JavaScript 来修改。
12、{{}}
其实这个也是一个指令,也许觉得和ng-bind差不多,但页面渲染略慢时可能会被看到。
另外,{{}}的执行远不如ng-bind,只是用起来很方便。
13、ng-bind
使用给定的变量或表达式的值来替换 HTML 元素的内容。
如果给定的变量或表达式修改了,指定替换的 HTML 元素也会修改。
ng-bind的行为和{{}}差不多,只是我们可以用这个指令来避免FOUC(Flash Of Unrendered Content)未渲染导致的闪烁。ng-bind-template指令
将给定表达式的值替换 HTML 元素的内容。
当你想在 HTML 元素上绑定多个表达式时可以使用 ng-bind-template 指令。
14、ng-cloak
ng-cloak也可以为我们解决FOUC。 ng-cloak会将内部元素隐藏,直到路由调用对应的页面。
FOUC :文档样式短暂失效
如果使用import方法对CSS进行导入,
会导致某些页面在Windows 下的Internet Explorer出现一些奇怪的现象:
以无样式显示页面内容的瞬间闪烁,这种现象称之为文档样式短暂失效(Flash of Unstyled Content)
存在完全是为了用户体验,
如果一个html界面angular.js还没加载进来,
那么界面会有{{}}这样的标志,如果{{}}标志多了,用户会一脸蒙蔽 啊,
ng-cloak如果加在根节点,那么界面的{{}}会被隐藏,等到{{}}完全编译成动态数据的时候界面才可见;
15、ng-if
如果ng-if中的表达式为false,则对应的元素整个会从DOM中移除而非隐藏,
但审查元素时你可以看到表达式变成注释了。如果相进行隐藏,可以使用ng-hide。
16、ng-switch
ngSwitch指令包含ng-switch-when、ng-switch-default功能类似switch,
ng-switch-when指条件条件符合将显示这个dom元素,
ng-switch-default指条件都不符合默认显示的元素。
17、ng-repeat
遍历集合(数组),给每个元素生成模板实例,每个实例的作用域中可以用一些特殊属性,如下
<ul ng-repeat="user in data"><ul>
$index : 表示当前item的索引,
$first : 如果item为第一个,那么$first为true ,
$middle : 如果item不是开头,不是结尾$middle为true,
$last : 如果item是最后一个, $last为true,
$even : 如果索引为偶数, 那么$even为true,否则为false
$odd : 同上, 索引为奇数$odd为true....;
18、ng-src
指令覆盖了 <img> 元素的 src 属性。
如果你使用了 AngularJS 代码设置图片地址,请使用 ng-src 指令替代 src 属性。
ng-src 指令确保的 AngularJS 代码执行前不显示图片。
界面加载的时候才不管img的标签src有什么
都会一并加载
如果图片的src包含了{{**}}这些字符
浏览器不会管这是什么东西
在渲染dom树的时候
会直接请求这个地址
angular框架是在DOMcontent加载完毕后才开始发挥作用。
假如我们模板中有一张图片如下:
<img src="http://m.cnblogs.com/142260/”{{imgUrl}}” />
那么在页面开始加载到ng编译完成之前,页面上会一直显示一张错误的图片,因为路径{{imgUrl}}还未被替换。
为了避免这种情况,我们使用ng-src指令,这样在路径被正确得到之前就不会显示找不到图片。同理,a标签的href属性也需要换成ng-href,这样页面上就不会先出现一个地址错误的链接。19、ng-href
覆盖了原生的 a 元素 href 属性。
如果在 href 的值中有 AngularJS 代码,则需要使用 ng-href 而不是 href。
ng-href 指令确保了链接是正常的,即使在 AngularJS 执行代码前点击链接。
<a href="{{myUrl}}">
20、ng-class
指令用于给 HTML 元素动态绑定一个或多个 CSS 类。
ng-class 指令的值可以是字符串,对象,或一个数组。
如果是字符串,多个类名使用空格分隔。
如果是对象,需要使用 key-value 对,key 为你想要添加的类名,value 是一个布尔值。只有在 value 为 true 时类才会被添加。
如果是数组,可以由字符串或对象组合组成,数组的元素可以是字符串或对象。
21、ng-click
点击事件
<element ng-click="event()"></element>
//
$scope.event=function(){}
22、ngKeyup
23、ngKeydown
24、ngKeypress
25、ngMousedown、ngMouseenter、ngMouseleave、ngMousemove、ngMouseover、ngMouseup
鼠标事件
26、ngTrim
去除左右空格
27、ng-include
指令用于包含外部的 HTML 文件。
包含的内容将作为指定元素的子节点。
ng-include 属性的值可以是一个表达式,返回一个文件名。
默认情况下,包含的文件需要包含在同一个域名下。
ng-include指令是指这个指令标签的innerHTML为指定的url
这个url为相对与当前目录的url地址或者绝对地址
angular会通过ajax请求该地址
然后把地址的内容作为指令元素innerHTML填充;
28、ng-list
指令将字符串转换为数组,并使用逗号分隔。
ng-list 指令还有另外一种转换方式,如果你有字符串数组希望在输入框中显示,你可以在 input 上使用 ng-list 指令。
ng-list 属性值定义了分隔符。
ng-list这个指令要和ng-model合起来用
ng-list在输入框的表现通过split(",")的数组才是实际的model
ng-list默认为","逗号
要设置成自定义的区分符,直接为ng-list赋值即可;
29、ng-pattren
匹配这个输入框的输入值是否符合这个正则,如果不匹配,这个元素会被加上ng-invalid的class, 如果匹配会被加上ng-valid的class
在表单校验中为详细介绍。。
30、ng-paste ng-copy ng-cut
用于告诉 AngularJS 文本在 HTML 元素上粘贴时需要执行的操作。
ng-paste 指令不会覆盖元素的原生 onpaste 事件, 事件触发时,ng-paste 表达式与原生的 onpaste 事件将都会执行。
如果输入框的值是粘帖的,那么ng-paste就为真。
ng-copy,ng-cut也是同理
31、ng-non-bindable
ng-non-bindable指令指该元素的内部{{**}}不被绑定和转义,不受angular的掌控:
32、ng-open
用于设置 details 列表的 open 属性。
如果 ng-open 的表达式返回 true 则 details 列表是可见的。
这个个人认为和ng-show, g-hide差不多, 区别是ng-open只能绑定details元素,
<details> 标签用于描述文档或文档某个部分的细节。
(details标签目前只有webkit浏览器支持)
33、input里的一些属性
novalidate属性(可无值)到form标签上,这样可以保证在表单不合法的情况下阻止浏览器继续提交数据。
使用 ng-model 属性进行绑定的表单,会自动的添加一些 class 样式,如:
@非必填表单
初始化时会添加 .ng-pristine 和 .ng-valid 两个class样式。当表单为非空时 class 样式会变成 .ng-valid 和 .ng-dirty 。其中将 .ng-pristine 变成了 .ng-dirty 。
@必填表单
初始化时会添加 .ng-pristine 、.ng-invalid 和 .ng-invalid-required 三个class样式。当表单为非空时 class 样式会变成 .ng-dirty 、.ng-valid 和 .ng-valid-required 。
ngMinLength,,ngMaxLength,ng-parttern,通过正则判断input是否匹配,
表单验证属性:
$dirty 表单有填写记录
$valid 字段内容合法的
$invalid 字段内容是非法的
$pristine 表单没有填写记录
ng-change,ng-vlaue就只是设置值而已 不双向绑定数据
(同样在表单验证中会详细介绍)
自定义指令
自定义是AngularJ非常强大而有有用的功能之一。它就相当于为我们写了公共的自定义DOM元素或Class属性或Attr属性,还可以在它的基础上来操作scope、绑定事件、更改样式等。通过这个Directive,我们可以封装很多公共指令,比如分页指令、自动补全指令等等。然后在HTML页面里只需要简单的写一行代码就可以实现很多强大的功能。
一般情况下,需要用Directive有下面的情景:
1.使你的Html更具语义化,不需要深入研究代码和逻辑即可知道页面的大致逻辑。
2.*抽象一个自定义组件,在其他地方进行重用。
指令的属性
先上代码
angular.module("MetronicApp").directive('directiveName', function factory(injectables) {
var directiveObject = {
priority: 0,
template: '<div>hello<span>world</span></div>',
templateUrl: 'directive.html',
replace: false,
transclude: false,
restrict: 'EA',
scope: false,
link: function postLink($scope, $element, $attrs) {
//code
}
controller: ['$scope', function ($scope) {
//code
}
};
return directiveObject
});
name就是指令名
对应上面代码中的directiveName
restrict 定义指令的出现形式
(字符串)可选参数,指明指令在DOM里面以什么形式被声明;
取值有:E(元素),A(属性),C(类),M(注释),其中默认值为A;
当然也可以两个一起用,比如EA.表示即可以是元素也可以是属性。
E(元素):<directiveName></directiveName>
A(属性):<div directiveName='expression'></div>
C(类): <div class='directiveName'></div>
M(注释):<--directive:directiveName expression-->
鉴于浏览器兼容问题。推荐 restrict :'A',即取值为属性。
scope 作用域,与值绑定
(1)默认值false。表示继承父作用域;
(2)true。表示继承父作用域,并创建自己的作用域(子作用域);
(3){}。表示创建一个全新的隔离作用域;
scope: {
lover: '=',
name: '@',
say: '&'
}
但是,如果我想将父scope中的属性传递给directive的scope怎么办呢?
directive 在使用隔离 scope(新的作用域) 的时候,提供了三种方法同隔离之外的地方交互:
'@' 绑定一个局部 scope 属性到当前 dom 节点的属性值。结果总是一个字符串,因为 dom 属性是字符串。
'&' 提供一种方式执行一个表达式在父 scope 的上下文中。如果没有指定 attr 名称,则属性名称为相同的本地名称。
'=' 需要实现双向数据绑定的时候使用。(最常使用)
template模板
可以使一段html代码。
template: '<div>hello<span>world</span></div>',
也可以是一个实例函数:
其中$element,是指使用此指令的元素,而$element,则实例的属性,它是一个由元素上所有的属性组成的集合(对象)
<div directive-name title="我是title"></div>
////////
template: function($element, $attrs){
var _html = '';
_html += '<div>' +'hello '+ $attrs.title+'</div>'; //这里的title就是这个指令里的title属性。
return _html;
}
};
同样有很明显的一个缺点,你也可以将整个template写得很复杂,但是,复杂的代码非常不易维护。并且你还得换行,得用字符串拼接每一行。过长的template建议使用templateUrl代替。
templateUrl模板
templateUrl为从指定地址获取模板内容。即你要在指令所在的容器中插入的一个.html文件。
当使用templateUrl模板时,需要运行一个服务器,不然使用templateUrl会报错 Cross Origin Request Script(CORS)错误。
由于加载html模板是通过异步加载的,若加载大量的模板会拖慢网站的速度,项目中对模板进行了缓存,是可取之处。如下
<script type='text/ng-template' id='directive.html'>
<div>
<h1>Hello World</h1>
<div>{{name}}</div>
</div>
</script>
这里的id属性就是被设置在templateUrl上用的。
这里的templateUrl类似于JSP中的include。有没有明白一点。
replace
是否用模板替换当前元素。
true : 将指令标签替换成temple中定义的内容,页面上不会再有<directive-name>标签;
false :则插入当前元素内,即模板的内容包在<directive-name>标签内部。默认false。
transculde:
是否使用ng-transculde来包含html中指令包含的原有的内容,接收两个参数true/false。默认值为false;
这个配置选项可以让我们提取包含在指令那个元素里面的内容,再将它放置在指令模板的特定位置。当你开启transclude后,你就可以使用ng-transclude来指明了应该在什么地方放置transcluded内容。
有些高阶的东西,用的不好就是bug。
link
可以简单理解为,当改自定义指令被angular 编译后,执行该方法。
主要的三个参数
$scope(当前指令内部作用域,和scope绑定有关),
$element(指的是html中的指令标签的对象,可以理解成$('directive对象'),类似jquery的选择器。),
$attrs(指令元素的属性的集合)
link在angular编译后执行
link函数主要用于操作dom元素,给dom元素绑定事件和监听.
controller
同link的区别在于
controller操作的是业务逻辑。所以通常使用的只有$scope参数。并且可以通过注入方式依赖其他模块。
如下
controller: ['$scope', '$location','UrlConfigService', function ($scope, $location,UrlConfigService) {
$scope.onActionClick = function (row, parentMethod) {
//code
};
}
compile
这个是在angular编译阶段执行的方法。compile在编译前执行,目的是负责把template(包括transclude所引用的)变成一个完整的DOM结构。
关于angular的编译过程这里给大家一个链接,可做了解。angular编译及生命周期
priority
多个指令设置在同一个元素上的执行优先级,执行顺序从低高:1>2>3;
priority的值为正整数,比如priority: 1,
ngHello的优先级肯定要高于ngWorld,不过实际中没人这么用,这里只做讲解。
angular.module("MetronicApp").directive("ngHello",function(){
return{
restrict: 'EA',
priority: 1,
link : function(){
//code
}
};
})
angular.module("MetronicApp").directive("ngWorld",function(){
return{
restrict: 'EA',
priority: 2,
link : function(){
//code
}
};
})
terminal
两个参数true/false 如果为true,本指令的优先级高于同一个元素上的其他指令,其他指令将停止执行。同样实际中不使用,只做了解。
angular.module("MetronicApp").directive("ngBook",function(){
return{
restrict: 'EA',
priority: 3,
terninal: true, //这里为true,ngHello和ngWorld都将停止执行
link : function(){
//code
}
};
})
指令的部分先介绍到这,如果在今后的实践中有发现不足和缺失再继续完善。此篇是让大家对指令有个规范了解。在项目中方便理解指令用法。例如table列表带分页(ng-table),查询列表(ng-tableinput) 展示列表(ng-list)(industry-field) 。也方便在今后自己封装,拆分一些公共功能模块。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。