AngularJs自定义指令详解

来源:互联网 发布:创业软件股份ceo 编辑:程序博客网 时间:2024/05/29 02:37

自定义指令的作用

熟悉AngularJS的朋友们都知道,angular有自定义指令的强大功能,使得Angular变得更加灵活。
利用它,我们可以把一个在WebApp中需要重复使用的功能独立出来,等需要使用的时候,打一个指令就能执行我们需要使用的该功能,
这样就减少了代码的重用,提高了代码可读性,也便于后期维护。

如何定义指令?

  1. 首先要注册一个module, 然后app.directive(‘指令名称’,Fn);
  2. 注意自定义指令中的函数必须返回一个对象,对象里面才是自定义指令的相关属性(详细内容请看下文)。
  3. 定义好指令后,在html中打相应的tag即可,有些指令可以作为元素名出现,而有些可以作为一个元素中的属性(下文将详细讨论)。
  4. 指令命名很重要,这关乎在解析dom的相应节点时,能不能读出你写的指令,下面的例子中,我定义了”myDirective”指令,而在html中,
    必须写成””。这里要记住的是,在app.direcitive中,名字如果有两个单词,第二个单词的首字母需要大写。
    在html中调用指令的时候需要把两个单词分开,当中加一个”-“,angular会根据大写字母的位置自动把这个字符串拆成两个单词,并且规定在html使用时,
    按照my-directive的形式来写。那有人问,我的指令如果是一个单词怎么办,比如我在app.direcitive中,定义’directive’,那在html中,
    我只要写 ““即可,切记千万不要在一个单词的时候首字母大写,这样会加载不出来的。
    (其他情况建议各位动手试试,亲测有效)

以下是一个简单的例子:
app.js代码:

var app = angular.module('DirectiveDemo', []);app.directive('myDirective', function() {    return {        restrict: 'AE',        template: '<h4>This is my directive</h4>'    }});

index.html代码:

<!DOCTYPE html><html>    <head>        <meta charset="utf-8" />        <title>Directive Demo</title>        <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,标签属性)


E(Element,直接作为标签)
C(Class,作为类)

M(注释)<–directive:my-directive expression–>

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: '<h4>This is my directive, visit a var in external scope: {{test}}</h4>'    }});

下面是验证该属性的示例,我在外部作用域创建了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: ‘

{{ myCtrl.msg }}

‘,
controllerAs: ‘myCtrl’,
controller: function() {
this.msg = “Hello World”
}
};
});

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

好了,本文就讲到这里,如果在理解上还存有问题,欢迎大家在下面评论,届时,小编将一一回答。

原创粉丝点击