指令是AngularJS1.x的灵魂,它能将特定功能的操作封装起来,只在页面引用指令标签即可。在这里,只简单介绍自定义指令,不对内置指令进行总结。
一、自定义指令
在angular中使用directive关键字来定义一个指令。
angualr.module('myApp',[])
.directie('myDirective',function() {
return {
restrict: 'A',
replace: true,
template: '<div>this is a directive</div'
scope:true,
controller: function() {}
link: function() {}
}
});
- restrict::指令的使用方式;有四种:
A:attribute,作为元素属性。<div myDirective='name'
>
E::element,作为元素。<myDirective></myDirective>
C:class,作为元素类名。<div class='myDirecitive'></div>
M:manual,作为注释。<!-- directive myDirective name -->
- template:指令使用的模板,用HTML字符串表示。
- templateUrl:从指定的url中加载指令使用的模板,‘src/index.html’
- replace:bool类型,是否用指定模板替换当前元素,若为false,则将模板追加到元素后面。
<div>
<myDirective></myDirective>
</div>
若replace为true,则最后的html代码为:
<div>this is a directive</div>
- transclude:bool类型,默认值为false。表示是否将当前元素的内容转移到模板中。主要用于解决元素中出现子标签的问题。当transclude为true时,将自定义的<myDirective&rt;指令标签替换成我们template或者templateUrl所指定的内容,但是指令内部所嵌套的子标签的北荣不会被替换掉。
<myDirective>
<span>this will not be replace</span>
</myDirective>
则html中显示的代码将会是;
this is a directive
<span>this will not be replace</span>
- scope: bool或者对象。用来指定scope的作用域。主要作用是隔离指令与所在控制器之间的作用域,或者隔离指令与指令之间的作用域。
1.scope:false时,不创建任何作用域,将父作用域当做当前作用域。这意味着,子作用域的任何改变都会影响到父作用域;
2.scope:true时,继承父作用域,并新建自己的独立作用域,这以为着子指令拥有了自己的作用域,同时又可以访问父指令的作用域数据;
3.scope:{ }时,不继承不作用域,新建自己独立的作用域。这意味着与父作用域没有任何联系,angular通过将当前节点的属性作为数据传递的桥梁(父作用域可以传递数据给节点属性,独立作用域可以通过一个映射关系来访问这个节点属性,并获取数据,从而达到访问父作用域的目的)
当scope的值是一个对象时,独立作用域字段与节点属性存在一个映射关系,可以有三种方式访问父作用域。
(1).“@attrName”:是一种值传递。代表指令内部作用域可以访问指令外部的属性,是一种单项绑定策略,这意味着,独立作用域的任何改变都不会影响父作用域,但是父作用域的改变则会影响独立作用域。
(2).“=attrName”:是一种引用传递。双向数据绑定策略,即独立作用域和它的父级作用域的任何改变都会影响到彼此。
(3).“&attrName”:函数绑定,可以访问父级作用域的函数,即调用父级作用域的函数(作为scope的attrName必须以“on”开头,如ondata:&)
angular.module('myApp',[])
.controller('myController',['$scope',function($scope) {
$scope.select = function() {console.log('scope function')}
}])
.directive('myDirective',function() {
return {
scope: {
onSelect: '&'
}
}
});
//HTML页面调用
<myDirective on-select=select()></myDirective>
- compile:compile阶段主要是对模板内容的处理,可以对模板内容进行修改。在这个阶段会把HTML模板片段转换为DOM对象,对DOM对象进行操作。
- link:link阶段主要对元素进行数据绑定(scope作用域绑定)和事件绑定。
1.当compile字段存在时,link字段被忽略,compile函数的返回值将作为link字段;
当compile字段不存在时,link字段存在。link分为“preLink”(可选)和“postLink”(可选)
2。angular在解析指令的时候,会先按一定顺序执行所有指令的“compile”函数,然后执行多有指令的“preLink”函数(如果存在),最后再执行所有指令的“postLink”函数
3.link字段或者compile字段的返回值可以有两种情况:
(1).返回值为函数。link会被认为是“postLink”
(2).返回值是一个对象。此时link作为“preLink”,link.preLink作为“preLink”,而link.post作为“postLink”
link: {
pre: function() {},
post: function() {}
}
4.节点指令的“preLink”是在所有子节点的“preLink”和“postLink”之前执行,所以一般在节点指令的“preLink”中,通过scope给子节点传递一些信息。
5.节点指令的“postLink”是在所有子节点指令的“preLInk”和“postLink”之后再执行的,也就意味着,当父节点指令执行完“postLink”时,子节点的“postLInk”已经都执行完毕了,此时,子DOM树已经稳定。所以,大部分的DOM操作和访问子节点的操作都会选择在这时执行。
angular.module('myApp',[])
.directive('myDirective',['$scope',function($scope) {
return {
restrict: 'EA',
template: '<div>this is my directive</div>',
replace: true,
scope: {
name: '='
},
link: function(scope,element) {
scope.name = 'Rorr'
}
}
}])
参考文章:Angular指令编译原理