Angularjs directive 参数详解

 1  app.directive('helloWorld', function() {
 2      return {
 3          restrict: 'AE',
 4          priority: 1,
 5          replace: 'true',
 6          scope: {},
 7          template: '<h3>Hello World!!</h3>',
 8          templateUrl: '',
 9          compile: function(tElem, attrs) {
10              //do optional DOM transformation here  
11              return function(scope, elem, attrs) {
12                  //linking function here  
13              }
14          },
15          link: function(scope, elem, attrs) {
16              //write your functions            
17          },
18          require: '^otherDirective',
19          controller: function($scope, $compile, $http) {
20              // $scope is the appropriate scope for the directive
21              this.addChild = function(nestedDirective) { // this refers to the controller
22                  console.log(nestedDirective.message);
23              };
24          }
25      }
26  });

priority

当有多个directive定义在同一个DOM元素时,有时需要明确它们的执行顺序。这属性用于在directive的compile function调用之前进行排序。如果优先级相同,则执行顺序是不确定的, 读者可以尝试.

restrict

设置指令在HTML如何作用

参数列表:

A - attribute

C - class

E - element

M - comment

replace

设置加载template/templateUrl时, 对directive自身这个标签的处理

参数列表:

false: 默认值, 保留这个标签的html代码

true: 用template/templateUrl的内容替换个这个directive标签

如:

1 <div hello-directive></div>
2 {
3   replace: true,
4   template: '<div>hi</div>'
5 }

页面结果为:

1 <div>hi</div>

反之(replace=false):

1 <div hello-directive>
2     <div>hi</div>
3 </div>

scope

默认情况下,指令获取它父节点的controller的scope.

参数列表:

false - 默认值, 会影响父scope

true - 创建一个子scope原型 继承 父scope

{}   - 隔离的scope,一个孤立存在不继承自父scope的scope

隔离scope和父scope之间的数据绑定

选择一:使用 @ 实现单向文本绑定, 父类可以修改子类

HTML:
1
<body ng-controller="MainCtrl"> 2 <input type="text" ng-model="color" placeholder="Enter a color"/> 3 <hello-world color-attr="{{color}}"/> 注意内容的写法是带"{{}}",用@进行单向绑定 4 </body>
JS:
1
app.directive('helloWorld', function() { 2 return { 3 scope: { 4 color: '@colorAttr' //当隔离scope属性和指令元素参数的名字一样时,可以只写'@' 5 }, 6 .... 7 // the rest of the configurations 8 }; 9 });

选择二:使用 = 实现双向绑定

HTML:
1
<body ng-controller="MainCtrl"> 2 <input type="text" ng-model="color" placeholder="Enter a color"/> 3 <hello-world color="color"/> 注意内容的写法是不带"{{}}",直接写model名,用=进行双向绑定 4 </body>
JS:
1
app.directive('helloWorld', function() { 2 return { 3 scope: { 4 color: '=' 5 }, 6 .... 7 // the rest of the configurations 8 }; 9 });

选择三:使用 & 在父scope中执行函数

HTML:
1
<body ng-controller="MainCtrl"> 2 <input type="text" ng-model="color" placeholder="Enter a color"/> 3 <say-hello sayHelloIsolated="sayHello()"/> 执行父scope中的sayHello()方法 4 </body>
JS:
1
app.directive('sayHello', function() { 2 return { 3 scope: { 4 sayHelloIsolated: '&' 5 }, 6 .... 7 // the rest of the configurations 8 }; 9 });

Transclusion(插入)

 把template/templateUrl插入指令模板中指定的位置

参数列表:

true   - 结合ng-transclude指令使用

element - 待研究

HTML:
1
<div output-text> 2 <p>This is div in index.html</p> 3 </div>
JS:
1
app.directive('outputText', function() { 2 return { 3 transclude: true,4 template: '<div ng-transclude></div><div>Include before this</div>' 5 }; 6 });

结果:

This is div in index.html

Include before this

Link函数

link函数主要用来为DOM元素添加事件监听、监视模型属性变化、以及更新DOM。实际上directive返回的对象就是个link,你可以直接return function(scope,elem,attrs){}来简写directive.

link: function(scope, elem, attrs) {  
      
 }  

参数列表: 

  • scope – 指令的scope。默认是父类的scope, 如果自己有自定义scope, 则指自己定义的.
  • elem   – 指令的jQLite(jQuery的子集)包装DOM元素。如果你在引入AngularJS之前引入了jQuery,那么这个元素就是jQuery元素,而不是jQLite元素。由于这个元素已经被jQuery/jQLite包装了,所以我们就     在进行DOM操作的时候就不需要再使用 $()来进行包装。
  • attr    – 一个包含了指令所在元素的属性的标准化的参数对象。举个例子,你给一个HTML元素添加了一些属性:,那么可以在 link 函数中通过 attrs.someAttribute 来使用它。

compile函数

compile 函数在 link 函数被执行之前用来做一些DOM改造。

要注意的是 compile 函数不能访问 scope,并且必须返回一个 link 函数。但是如果没有设置 compile 函数,你可以正常地配置 link 函数,如果有了compile,就不能用link,link函数由compile返回.

大多数的情况下,你只需要使用 link 函数。这是因为大部分的指令只需要考虑注册事件监听、监视模型、以及更新DOM等,这些都可以在 link 函数中完成。 但是对于像 ng-repeat 之类的指令,需要克隆和重复 DOM 元素多次,在 link 函数执行之前由 compile 函数来完成。这就带来了一个问题,为什么我们需要两个分开的函数来完成生成过程,为什么不能只使用一个?要回答好这个问题,我们需要理解指令在Angular中是如何被编译的!

指令是如何被编译的

当应用引导启动的时候,Angular开始使用 $compile 服务遍历DOM元素。这个服务基于注册过的指令在标记文本中搜索指令。一旦所有的指令都被识别后,Angular执行他们的 compile 方法。如前面所讲的,compile 方法返回一个 link 函数,被添加到稍后执行的 link 函数列表中。这被称为编译阶段。如果一个指令需要被克隆很多次(比如 ng-repeat),compile函数只在编译阶段被执行一次,复制这些模板,但是link 函数会针对每个被复制的实例被执行。所以分开处理,让我们在性能上有一定的提高。这也说明了为什么在 compile 函数中不能访问到scope对象。 在编译阶段之后,就开始了链接(linking)阶段。在这个阶段,所有收集的 link 函数将被一一执行。指令创造出来的模板会在正确的scope下被解析和处理,然后返回具有事件响应的真实的DOM节点。

controller 函数和 require

如果你想要允许其他的指令和你的指令发生交互时,你需要使用 controller 函数。比如有些情况下,你需要通过组合两个指令来实现一个UI组件。那么你可以通过如下的方式来给指令添加一个 controller 函数。

app.directive('outerDirective', function() {
  return {
    scope: {},
    restrict: 'AE',
    controller: function($scope, $compile, $http) {
      // $scope is the appropriate scope for the directive
      this.addChild = function(nestedDirective) { // this refers to the controller
        console.log('Got the message from nested directive:' + nestedDirective.message);
      };
    }
  };
});

这个代码为指令添加了一个名叫 outerDirective 的controller。当另一个指令想要交互时,它需要声明它对你的指令 controller 实例的引用(require)。可以通过如下的方式实现:

app.directive('innerDirective', function() {
  return {
    scope: {},
    restrict: 'AE',
    require: '^outerDirective',
    link: function(scope, elem, attrs, controllerInstance) {
      //the fourth argument is the controller instance you require
      scope.message = "Hi, Parent directive";
      controllerInstance.addChild(scope);
    }
  };
});

相应的HTML代码如下:

<outer-directive>
  <inner-directive></inner-directive>
</outer-directive>

require:

‘^outerDirective’ 告诉Angular在元素以及它的父元素中搜索controller。这样被找到的 controller 实例会作为第四个参数被传入到 link 函数中。在我们的例子中,我们将嵌入的指令的scope发送给父亲指令。

如果找不到这个名称对应的controller,那么将会抛出一个error。

名称可以加入以下前缀:

? - 不要抛出异常。这使这个依赖变为一个可选项。

^ - 允许查找父元素的controller

 

如果你想尝试这个代码的话,请在开启浏览器控制台的情况下打开这个Plunker。同时,这篇Angular官方文档上的最后部分给了一个非常好的关于指令交互的例子,是非常值得一读的。

controller,link,compile执行顺序

如果有compile: controller先运行,compile后运行,link不运行

如果没有compile: controller先运行,link后运行,link和compile不兼容, 前文已说过.

 

 

 

 参考文档:

http://blog.jobbole.com/62249/

http://blog.jobbole.com/62999/

http://developer.51cto.com/art/201403/431734.htm

转载于:https://www.cnblogs.com/awakening/p/3821329.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值