var app = angular.module("app",[]);
//第一个参数:指令的名称,使用驼峰命名
//第二个参数:回调函数,回调函数内部返回对象
app.directive("hiHello",function () {
return {
//执行的代码,参数,写在这里
}
});
directive的参数
restrict : String
设置自定义指令的html格式
restrict的取值表
| E| C | M | A |
|:---------------:|:------:|
| element | attribute | class | 注释 |
<body>
<!-- 1 : 使用指令的第一种方式 -->
<hi-hello>若其中有内容,则被替换掉</hi-hello>
<!-- 2: 属性 -->
<div hi-hello></div>
<!-- 3:类名 -->
<div class="hi-hello"></div>
<!-- 4:注释 指令名后面保留一个空格 -->
<!-- directive:hi-hello -->
</body>
<script type="text/javascript">
var app = angular.module("app",[]);
app.directive("hiHello",function () {
return {
/* ECMA
* E : element
* A : attribute
* C : class
* M : 注释
*/
restrict:"EACM",//可以组合使用,顺序不限,得大写 (默认值为EA)
// 如果使用M,必须得配合使用 replace(替换)
replace:true,//默认值为false 表示是否替换当前元素
//设置模板
template:"<h1>随便写的信息</h1>",
}
});
</script>
replace : Boolean or String
(布尔型)默认为false(模板内容会加载到标签内部),true(模板内容会替换当前标签),即是否替换当前元素中已有的内容
replace:true,
注意:如果使用M,必须得配合使用 replace(替换)
###priority : Number
优先级,可忽略,默认为0
注意: ng-repeat 的优先级为1000,这样就可以保证在同一元素上,它总是在其他指令之前被调用
###terminal : Boolean
如果为false,则Angular停止运行当前元素上比本指令优先级低的指令。优先级相同的指令还是会被执行
注意: ng-if 的优先级略高于 ng-view
priority和terminal的综合运用
<body>
<hello well good>
<div>Hello World!!!</div>
</hello>
</body>
<script src="js/angular.min.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
//terminal和priority两个参数只能在同一个元素上设置多个指令才有效
app.directive("hello",function(){
return {
restrict : "E",
priority : 1,
link : function(){
console.log("hello");
}
}
});
app.directive("well",function(){
return {
restrict : "A",
priority : 2,
link : function(){
console.log("well");
}
}
});
app.directive("good",function(){
return {
restrict : "A",
terminal : true, //这里为true,hello、well指令将停止执行
priority : 3,
link : function(){
console.log("good");
}
}
});
app.controller("myCtrl",function($scope){
})
</script>
template : String or Template Function
设置模板,必须设置
template:"<h1>随便写的信息</h1>",
//template:function(tElement, tAttrs){...},
###templateUrl: String
(字符串或函数)
外部路径的字符串
接受两个参数的函数,参数为 tElement 和 tAttrs ,并返回一个外部HTML文件路径的字符串
模板加载后,AngularJS会将它默认缓存到$templateCach服务中。
注意:templateUrl 可以提前加载模块到缓存中,提高加载速度
templateUrl : "html/first.html",
###scope: Boolean or Object
当一个控制器实现多个数据时,就需要用到scope属性实现不同的数据。如果要创建一个能够从外部原型继承作用域的指令,将 scope 属性设置为 true
scope属性的独立作用域
为true时,从父作用域继承并创建一个自己的作用域
为false(默认)时,全部继承父作用域
1).controller属性
配置属于每个指令自己作用域上的数据(共有),而ng-controller 的作用就是从父级作用域继承并创建一个新的子作用域。
controller : function($scope){
$scope.age = 20
}
设置为一个对象,则能设置 隔离作用域, scope 属性设置为一个空对象 {} 。如果这样做了,指令的模板就无法访问外部作用域了,代码如下:
directive('myDirective', function() {
return {
restrict: 'A',
scope: {},
priority: 100,
template: '<div>Inside myDirective {{ myProperty }}</div>'
};
});
隔离作用域
将scope属性设置为一个对象,而不是布尔值。隔离作用域默认和父作用域没关系,无法继承它的属性
1). 设置模板中数据的作用域和绑定规则:
|@| = |&|
|:---------------:|:------:|
| 把当前属性作为字符串传递 |与父作用域中的属性进行绑定素|与父作用域中的函数进行绑定|
"@" : 本地作用域属性:使用当前指令中的数据和DOM属性的值进行绑定
“=” : 双向绑定:本地作用域上的属性同父级作用域上的属性进行双向的数据绑定。
“&” : 父级作用域绑定:通过 & 符号可以对父级作用域进行绑定
scope : {
name : "@" //属性和标签内的属性写一样
}
scope: {
ngModel: '=', // 将ngModel同指定对象绑定
onSend: '&', // 将引用传递给这个方法
fromName: '@' // 储存与fromName相关联的字符串
}
transclude: Boolean
默认为false,需要创建一个可以包含任意内容的指令时, 才使用 transclude: true 。
注意:只要使用了 transclude 参数,那么在控制器(下面马上会介绍)中就无法正常监听数据模型的变化了
controller: String or function
controller: String or function(scope, element, attrs, transclude, otherInjectables) { ... }
注册在应用中的控制器的构造函数,使用函数创建内联控制器
angular.module('myApp',[]).directive('myDirective', function() {
restrict: 'A',
controller:function($scope, $element, $attrs, $transclude) {
// 控制器逻辑放在这里
}
})
controllerAs: String
可以在指令中创建匿名控制器
angular.module('myApp',[]).directive('myDirective', function() {
return {
restrict: 'A',
template: '<h4>{{ myController.msg }}</h4>',
controllerAs: 'myController',
controller: function() {
this.msg = "Hello World"
}
};
});
require: String
(字符串或数组)字符串代表另外一个指令的名字,如果没有前缀,指令将会在自身所提供的控制器中进行查找,如果没有找到任何控制器(或具有指定名字的指令)就抛出一个错误。例如:
如果不使用 ^ 前缀,指令只会在自身的元素上查找控制器。
require: 'ngModel'
使用 ? 如果在当前指令中没有找到所需要的控制器,会将 null 作为传给 link 函数的第四个参数
require: '?ngModel'
使用 ^ 如果添加了 ^ 前缀,指令会在上游的指令链中查找 require 参数所指定的控制器。
require: '^ngModel'
使用 ^? 将前面两个选项的行为组合起来,我们可选择地加载需要的指令并在父指令链中进行查找。
require: '^?ngModel',
link和compile
link: link: function(scope, iElement, iAttrs) { ... },
compile: compile: function(tElement, tAttrs, transclude) { ... },
compile 选项本身并不会被频繁使用,但是 link 函数则会被经常使用。当我们设置了 link 选项, 实际上是创建了一个 postLink() 链接函数, 以便 compile() 函数可以定义链接函数。
compile 和 link 选项是互斥的。如果同时设置了这两个选项,那么会把 - compile所返回的函数当作链接函数,而 link 选项本身则会被忽略。
通常情况下,如果设置了 compile 函数,说明我们希望在指令和实时数据被放到DOM中之前进行DOM操作,在这个函数中进行诸如添加和删除节点等DOM操作是安全的。
//用 link 函数创建可以操作DOM的指令。
require : 'SomeController',
link: function(scope, element, attrs, SomeController) {
// 在这里操作DOM,可以访问required指定的控制器
}
compile: function(tElement, tAttrs, transclude) {
return {
pre: function(scope, iElement, iAttrs, controller) { ... },
post: function(scope, iElement, iAttrs, controller) { ... }
}
// 或者
return function postLink(...) { ... }
}
};
注意:指令的生命周期开始于 $compile 方法并结束于 link 方法