浅谈angularJS指令的属性

时间:2023-03-08 22:14:42
浅谈angularJS指令的属性
  • restrict – 这个属性用来指定指令在HTML中如何使用(指令的四种表示方式)。我们使用 ‘AE’,这个指令可以被当作新的HTML元素或者属性来使用。如果要允许指令被当作class来使用,我们将 restrict 设置成 ‘AEC’。
  • template – 这个属性规定了指令被Angular编译和链接(link)后生成的HTML标记。这个属性值不一定要是简单的字符串。template 可以非常复杂,而且经常包含其他的指令,以及表达式({{ }})等。更多的情况下你可能会见到 templateUrl, 而不是 template。所以,理想情况下,你应该将模板放到一个特定的HTML文件中,然后将 templateUrl 属性指向它。
  • replace – 这个属性指明生成的HTML内容是否会替换掉定义此指令的HTML元素。我们用 <hello-world></hello-world>的方式使用我们的指令,并且将 replace 设置成 true。所以,在指令被编译之后,生成的模板内容替换掉了 <hello-world></hello-world>。如果你将 replace 设置成 false,也就是默认值,那么生成的模板会被插入到定义指令的元素中。
  • link

我们注意到指令定义中的 link 函数。 它有三个参数:

    • scope – 指令的scope。指令的scope一般是父controller的scope。
    • elem – 指令的jQLite(jQuery的子集)包装DOM元素。如果你在引入AngularJS之前引入了jQuery,那么这个元素就是jQuery元素,而不是jQLite元素。由于这个元素已经被jQuery/jQLite包装了,所以我们就在进行DOM操作的时候就不需要再使用 $()来进行包装。
    • attr – 一个包含了指令所在元素的属性的标准化的参数对象。举个例子,你给一个HTML元素添加了一些属性:,那么可以在 link 函数中通过 attrs.someAttribute 来使用它。
    • link函数主要用来为DOM元素添加事件监听、监视模型属性变化、以及更新DOM。
  • compile -这个函数在 link 函数被执行之前用来做一些DOM改造。它接收下面的参数:

    • tElement – 指令所在的元素
    • attrs – 元素上赋予的参数的标准化列表

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

    1. app.directive('test', function() {
    2. return {
    3. compile: function(tElem,attrs) {
    4. //do optional DOM transformation here
    5. return function(scope,elem,attrs) {
    6. //linking function here
    7. };
    8. }
    9. };
    10. });

    大多数的情况下,你只需要使用 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节点。

  • 改变指令的Scope

    默认情况下,指令获取它父节点的controller的scope。但这并不适用于所有情况。如果将父controller的scope暴露给指令,那么他们可以随意地修改 scope 的属性。在某些情况下,你的指令希望能够添加一些仅限内部使用的属性和方法。如果我们在父的scope中添加,会污染父scope。 其实我们还有两种选择:

    • 一个子scope – 这个scope原型继承子父scope。
    • 一个隔离的scope – 一个孤立存在不继承自父scope的scope。

    这样的scope可以通过指令定义对象中 scope 属性来配置。下面的代码片段是一个例子:

    1. app.directive('helloWorld', function() {
    2. return {
    3. scope: true,  // use a child scope that inherits from parent
    4. restrict: 'AE',
    5. replace: 'true',
    6. template: '<h3>Hello World!!</h3>'
    7. };
    8. });

    上面的代码,让Angular给指令创建一个继承自父socpe的新的子scope。 另外一个选择,隔离的scope:

    1. app.directive('helloWorld', function() {
    2. return {
    3. scope: {},  // use a new isolated scope
    4. restrict: 'AE',
    5. replace: 'true',
    6. template: '<h3>Hello World!!</h3>'
    7. };
    8. });

    这个指令使用了一个隔离的scope。隔离的scope在我们想要创建可重用的指令的时候是非常有好处的。通过使用隔离的scope,我们能够保证我们的指令是自包含的,可以被很容易的插入到HTML应用中。 它内部不能访问父的scope,所保证了父scope不被污染。

  • transclude:

    在使用angularjs创建指令时,

    例如:

    var myApp=angular.module('testModule',[]);

    myApp.directive('pane', function(){
    return {
    restrict: 'E',
    transclude:true,       
    scope: { title:'@' },
    template: '<div style="border: 1px solid black;">' +
    '<div style="{{title}}</div>' +
    '<div ng-transclude></div>' +
    '</div>'
    };
    });

    当设置transclude为true,pane中的内容(包括{{}}中的内容)会被保留到设置ng-transclude指令的区域(下划线的地方)。

    html:

    <input ng-model="title" ng-init="text='title'"><br>
    <textarea ng-model="text" ng-init="text='text'"></textarea> <br/>
    <pane title="{{title}}">{{text}}</pane>

更详细内容请看:http://blog.jobbole.com/62249/