• 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

  • 相关阅读:
    Java 进程占用内存过多,幕后元凶原来是线程太多
    领域驱动设计系列文章(3)——有选择性的使用领域驱动设计
    领域驱动设计系列文章(1)——通过现实例子显示领域驱动设计的威力
    RabbitMQ
    Redis与Memcached的区别
    memcached源码分析-----slab内存分配器
    C# Finalize和Dispose的区别
    [IoC容器Unity]第四回:使用范例
    [IoC容器Unity]第三回:依赖注入
    [IoC容器Unity]第二回:Lifetime Managers生命周期
  • 原文地址:https://www.cnblogs.com/awakening/p/3821329.html
Copyright © 2020-2023  润新知