自定义指令的作用
熟悉AngularJS的朋友们都知道,angular有自定义指令的强大功能,使得Angular变得更加灵活。
利用它,我们可以把一个在WebApp中需要重复使用的功能独立出来,等需要使用的时候,打一个指令就能执行我们需要使用的该功能,
这样就减少了代码的重用,提高了代码可读性,也便于后期维护。
如何定义指令?
以下是一个简单的例子:
app.js代码:
var app = angular.module('DirectiveDemo', []);
app.directive('myDirective', function() {
return {
restrict: 'AE',
template: 'This is my directive
'
}
});
index.html代码:
<html>
<head>
<meta charset="utf-8" />
<title>Directive Demotitle>
<script type="text/javascript" src="js/lib/angular.1.6.4/angular.min.js">script>
<link rel="stylesheet" href="css/bootstrap.3.3.6/css/bootstrap.min.css" />
<script type="text/javascript" src="lib/bootstrap.3.3.6/bootstrap.min.js">script>
<script type="text/javascript" src="app.js">script>
head>
<body ng-app="DirectiveDemo" ng-controller="DemoController">
<div class="page-header">
<h1>Directive Demo h1><br />
div>
<div class="container-fluid">
<div class="row">
<div class="col-md-12">
<my-directive>my-directive>
div>
div>
div>
body>
html>
下面是自定义指令的属性详解:
我们首先进入定义指令的环境,
1.restrict属性
restrict: String类型,
restrict属性的值是string字符串,用来定义该指令在html的DOM中以某种形式声明。
声明形式有四种:A, E, C, M
restrict默认‘EA’
A(Atribute,标签属性)
2.priority
priority: Number类型,
priority是用来定义执行优先级的,可忽略,默认为0, ngRepeat的优先级为1000,这样就可以保证在同一元素上,ne-repeat总是在其他指令之前被调用。
3.terminal属性
terminal: Boolean类型,
如果terminal为false,则这个参数用来告诉AngularJS停止运行当前元素上比本指令优先级低的指令。优先级相同的指令还是会被执行。
4.template和templateUrl属性
template: String类型 or 返回一个含有html代码的字符串对象的函数
templateUrl: String类型 or 返回一个url字符串对象的函数
模板加载后,AngularJS会将它默认缓存到 $templateCache 服务中,这样可以提前加载模块到缓存中,提高加载速。
5.replace属性(默认为false)
replace: Boolean or String类型,
replace值为false时,模板内容会加载到自定义标签内部;
replace值为true时,模板内容会替换当前自定义标签标签;
6.scope属性(默认为false)
scope: Boolean or Object类型,
scope值为false时,可以理解成指令内部并没有一个新的scope,它和指令以外的代码共享同一个scope;
scope值为true时,会从父作用域继承并创建一个新的作用域对象;
// ng-controller 的作用,就是从父级作用域继承并创建一个新的子作用域。
//如果要创建一个能够从外部原型继承作用域的指令,将 scope 属性设置为 true
scope值为一个对象,则能设置隔离作用域, scope 属性设置为一个空对象 {} 。这样,指令的模板就不能访问外部作用域了:
我们对上述实例进行修改:
//Define `myApp` module
var app = angular.module('DirectiveDemo', []);
app.controller('DemoController', function($scope) {
$scope.test = 1;
});
app.directive('myDirective', function() {
return {
restrict: 'AE',
scope:{},
template: 'This is my directive, visit a var in external scope: {
{test}}
'
}
});
下面是验证该属性的示例,我在外部作用域创建了test变量,在自定义指令的模版中,访问改变量。
如果scope值不是一个对象,那就不会设置隔离作用域了,那也就能访问外部变量。但是scope一旦设为一个对象,便不能访问了,见下图:
在scope对象中,还可以使用“@” “=” “&”,来设置模板中数据的作用域和绑定规则
“@” 本地作用域属性:使用当前指令中的数据和DOM属性的值进行绑定
“=” 双向绑定:本地作用域上的属性同父级作用域上的属性进行双向的数据绑定。
“&” 父级作用域绑定:通过 & 符号可以对父级作用域进行绑定
例如
scope: {
ngModel: ‘=’, // 将ngModel同指定对象绑定
onSend: ‘&’, // 将引用传递给这个方法
fromName: ‘@’ // 储存与fromName相关联的字符串
}
具体的scope属性如何使用请参考实例:http://blog.csdn.net/victoryzn/article/details/77140532
7.transclude属性(默认为false)
transclude: Boolean类型,
只有当你希望创建一个可以包含任意内容的指令时, 才使用 transclude: true 。
如果指令使用了 transclude 参数,那么在控制器中就无法正常监听数据模型的变化了。
具体的transclude属性如何使用请参考实例:http://blog.csdn.net/victoryzn/article/details/76854913
8.controller属性
String(Controller名字)
或者
function(scope, element, attrs, transclude, otherInjectables) { … },
注册在应用中的控制器的构造函数
使用函数创建内联控制器,例如
app.directive(‘myDirective’, function() {
restrict: ‘AE’,
controller:function( scope, element, attrs, transclude) {
}
});
给controller取别名,这里需要用构造函数的方式创建变量,这样才能在指令中访问
controllerAs: String,
app.directive(‘myDirective’, function() {
return {
restrict: ‘A’,
template: ‘
9.require属性
require: String类型,
这里require属性值需要的是另外一个指令名字的字符串,如果没有前缀,指令将会在自身所提供的控制器中进行查找,
如果没有找到任何控制器(或具有指定名字的指令)就抛出一个错误。
基本写法如下:
require: ‘ngModel’
如果使用 ‘?’,这就代表如果在当前指令中没有找到所需要的控制器,会将 null 作为传给 link 函数的第四个参数
require: ‘?ngModel’
使用 ‘^’, 这就代表指令会在上游的指令链中查找 require 参数所指定的控制器。
require: ‘^ngModel’
使用 ‘^?’ 将前面两个选项的行为组合起来,可选择性地加载需要的指令并在父指令链中进行查找。
require: ‘^?ngModel’,
10.compile 和 link属性
目前,网络上已经有许多相关的文章,但是讨论compile与link的区别的不是很多。
大部分的文章会说compile只会在ng内部用到,一般只推荐使用link函数。为了更好地理解Angular是怎么运行的,把这个知识点搞清楚将会
提升你的开发等级。
compile: function(tElement, tAttrs, transclude) {
return {
pre: function(scope, iElement, iAttrs, controller) { },
post: function(scope, iElement, iAttrs, controller) { }
}
// 或者
return function postLink(scope, iElement, iAttrs,controller) {}
}
};
});
link: function(scope, iElement, iAttrs,controller) {},
当我们设置了 link 选项, 实际上是创建了一个 postLink() 链接函数, 以便 compile() 函数可以定义链接函数。
compile 和 link 选项是互斥的。如果同时设置了这两个选项,那么会把 compile
所返回的函数当作链接函数,而 link 选项本身则会被忽略。
通常情况下,如果设置了 compile 函数,说明我们希望在指令和实时数据被放到DOM里面之前
进行DOM操作,在这个函数中进行诸如添加和删除节点等DOM操作是安全的。
关于自定义指令中的controller、compile以及link函数一直是开发者最头疼得事情,具体区别请点击:
http://blog.csdn.net/victoryzn/article/details/77480997
好了,本文就讲到这里,如果在理解上还存有问题,欢迎大家在下面评论,届时,小编将一一回答。