angularjs指令中的compile与link函数详解补充

平凡大家在利用ng中的指令的时候,用的链接函数最多的是link属性,下边那篇小说将告诉大家complie,pre-link,post-link的用法与差别.

angularjs里的一声令下万分神奇,允许你创建丰富语义化以及中度重用的零部件,能够驾驭为web
components的先驱者.

网上已经有不少介绍怎么使用指令的篇章以及有关书籍,相互比较的话,很少有介绍compile与link的界别,更别说pre-link与post-link了.

绝超过百分之三十三科目只是简短的说下compile会在ng内部使用,而且提议大家只用link属性,大多数下令的例子里都以如此的

那是卓殊不幸的,因为不易的知道那么些函数的区分会增加你对ng内部运行机理的明白,有助于你付出更好的自定义指令.

因而随后本身联合来看上面包车型的士始末一步步的去了然那一个函数是什么样以及它们应该在如何时候用到

本文要是你已经对指令有必然的打听了,假使没有的话强烈建议你看看那篇小说AngularJS
developer guide section on directives

 NG中是如何处理指令的

发端分析在此之前,先让大家看看ng中是何许处理指令的.

当浏览器渲染三个页面时,本质上是读html标识,然后建立dom节点,当dom树成立达成之后广播二个轩然大波给我们.

当您在页面中接纳script标签加载ng应用程序代码时,ng监听下面的dom完成事件,查找带有ng-app属性的成分.

当找到这么的因素之后,ng发轫拍卖dom以那些成分的起源,所以只要ng-app被添加到html成分上,则ng就会从html成分开首拍卖dom.

从那一个源点先导,ng开始递归查找全体子成分里面,符合应用程序里定义好的吩咐规则.

ng怎么样处理指令其实是借助于它定义时的对象属性的,你能够定义几个compile也许一个link函数,可能用pre-link和post-link函数来取代link.

于是那么些函数的界别吗?为何要使用它?以及怎么样时候利用它呢?

带着这几个题材随即本人一步一步来解答那么些迷团吧

一段代码

为了解释那么些函数的不一致,上面笔者将运用3个简练易懂的例子

1.万一您有此外的难点,请不要犹豫急忙在底下加上你的褒贬吧.

看望上面一段html标签代码

 

复制代码代码如下:

  <level-one>
        <level-two>
            <level-three>
                Hello 
            </level-three>
        </level-two>
    </level-one>

 

下一场是一段js代码

 

复制代码代码如下:

var app = angular.module(‘plunker’, []);

 

    function createDirective(name){
      return function(){
        return {
          restrict: ‘E’,
          compile: function(tElem, tAttrs){
            console.log(name + ‘: compile’);
            return {
              pre: function(scope, iElem, iAttrs){
                console.log(name + ‘: pre link’);
              },
              post: function(scope, iElem, iAttrs){
                console.log(name + ‘: post link’);
              }
            }
          }
        }
      }
    }

    app.directive(‘levelOne’, createDirective(‘levelOne’));
    app.directive(‘levelTwo’, createDirective(‘levelTwo’));
    app.directive(‘levelThree’, createDirective(‘levelThree’));

 

结果分外简单:让ng来处理八个嵌套指令,并且每一种指令都有友好的complile,pre-link,post-link函数,每一个函数都会在控制台里打印一行东西来标识自个儿.

其一例子能够让我们简要的打听到ng在拍卖指令时,内部的流程

代码输出

上边是二个在支配台出口结果的截图

图片 1

要是想协调节和测试一下那么些事例的话,请点击this plnkr,然后在控制台查看结果.

剖析代码

先是个要注意的是这个函数的调用顺序:

复制代码代码如下:

 // COMPILE PHASE
    // levelOne:    compile function is called
    // levelTwo:    compile function is called
    // levelThree:  compile function is called

 

    // PRE-LINK PHASE
    // levelOne:    pre link function is called
    // levelTwo:    pre link function is called
    // levelThree:  pre link function is called

    // POST-LINK PHASE (Notice the reverse order)
    // levelThree:  post link function is called
    // levelTwo:    post link function is called
    // levelOne:    post link function is called

 

这些事例清晰的展现出了ng在link在此以前编写翻译全数的吩咐,然后link要又分为了pre-link与post-link阶段.

留意下,compile与pre-link的执行顺序是逐一执行的,可是post-link正好相反.

故而地点已经路人皆知标识出了不相同的等级,然而compile与pre-link有啥分别吧,都以一致的执行顺序,为啥还要分成五个差别的函数呢?

DOM

为了挖的更深一点,让我们简要的修改一下上边的代码,它也会在各个函数里打字与印刷参数列表中的element变量

 

复制代码代码如下:

var app = angular.module(‘plunker’, []);

 

    function createDirective(name){ 
      return function(){
        return {
          restrict: ‘E’,
          compile: function(tElem, tAttrs){
            console.log(name + ‘: compile => ‘ + tElem.html());
            return {
              pre: function(scope, iElem, iAttrs){
                console.log(name + ‘: pre link => ‘ +
iElem.html());
              },
              post: function(scope, iElem, iAttrs){
                console.log(name + ‘: post link => ‘ +
iElem.html());
              }
            }
          }
        }
      }
    }

    app.directive(‘levelOne’, createDirective(‘levelOne’));
    app.directive(‘levelTwo’, createDirective(‘levelTwo’));
    app.directive(‘levelThree’, createDirective(‘levelThree’));

 

只顾下console.log里的输出,除了输出原始的html标记基本没其余改变.

本条相应力所能及强化我们对于这一个函数上下文的驾驭.

重国民党的新生活运动行代码看看

输出

下边是二个在控制台出口结果的截图

图片 2

假使你还想协调拨运输行看看效果,能够点击this
plnkr,
然后在控制台里查看输出结果.

观察

输出dom的结果能够暴露一些幽默的业务:dom内容在compile与pre-link七个函数中是分裂等的

由此发生了怎么样呢?

Compile

咱俩早就知晓当ng发现dom塑造完成时就开始拍卖dom.

为此当ng在遍历dom的时候,遇到level-one成分,从它的定义那里了然到,要实践一些须求的函数

因为compile函数定义在level-one指令的指令对象里,所以它会被调用并传递2个element对象作为它的参数

比方您仔细观看,就会看出,浏览器创造那几个element对象时,依然是最原始的html标记

1.在ng中,原始dom平日用来标识template
element,所以小编在定义compile函数参数时就用到了tElem名字,这一个变量指向的正是template
element.

一经运转levelone指令中的compile函数,ng就会递归深度遍历它的dom节点,然后在level-two与level-three上面重复那个操作.

Post-link

深切摸底pre-link函数在此之前,让我们来看望post-link函数.

2.只要您在概念指令的时候只行使了二个link函数,那么ng会把这一个函数当成post-link来拍卖,因而大家要先探究那个函数
当ng遍历完全数的dom并运维完全部的compile函数之后,就反向调用相关联的post-link函数.

dom以往开首反向,并履行post-link函数,因而,在前边那种反向的调用看起来有点意外,其实这么做是这一个有意义的.

图片 3

当运行李包裹括子指令的通令post-link时,反向的post-link规则能够确认保障它的子指令的post-link是早已运营过的.

所以,当运营level-one指令的post-link函数的时候,大家能够保险level-two和level-three的post-link其实都早就运维过了.

那正是怎么人们都认为post-link是最安全或许暗中同意的写作业逻辑的地方.

唯独怎么那边的element跟compile里的又分歧呢?

假设ng调用过三令五申的compile函数,就会创建三个template
element的element实例对象,并且为它提供三个scope对象,这些scope有大概是新实例,也有大概是早已存在,恐怕是个子scope,也有也许是单独的scope,这一个都得依靠指令定义对象里的scope属性值

之所以当linking发生时,这几个实例element以及scope对象已经是可用的了,并且被ng作为参数传递到post-link函数的参数列表中去.

1.自小编个人总是选拔iElem名称来定义1个link函数的参数,并且它是指向element实例的

据此post-link(pre-link)函数的element参数对象是三个element实例而不是2个template
element.

为此地点例子里的出口是分裂的

Pre-link

当写了七个post-link函数,你能够确定保障在推行post-link函数的时候,它的持有子级指令的post-link函数是早已履行过的.

在大部的图景下,它都能够做的更好,因此普通大家都会使用它来编排指令代码.

不过,ng为我们提供了3个附加的hook机制,那正是pre-link函数,它能够保险在进行全部子指令的post-link函数在此以前.运维一些其他代码.

那句话是值得反复推敲的

pre-link函数能够保障在element实例上以及它的全数子指令的post-link运营之前执行.

由此它使的post-link函数反向实施是一对一有含义的,它自个儿是原有的顺序执行pre-link函数

那也意为着pre-link函数运转在它全部子指令的pre-link函数从前,所以完全的说辞正是:

二个因素的pre-link函数能够确定保证是运作在它具有的子指令的post-link与pre-link运行以前实施的.见下图:

图片 4

回顾

比方大家回头看看上边原始的输出,就能领悟的认出到底爆发了什么:

复制代码代码如下:

    // HERE THE ELEMENTS ARE STILL THE ORIGINAL TEMPLATE ELEMENTS

 

    // COMPILE PHASE
    // levelOne:    compile function is called on original DOM
    // levelTwo:    compile function is called on original DOM
    // levelThree:  compile function is called on original DOM

    // AS OF HERE, THE ELEMENTS HAVE BEEN INSTANTIATED AND
    // ARE BOUND TO A SCOPE
    // (E.G. NG-REPEAT WOULD HAVE MULTIPLE INSTANCES)

    // PRE-LINK PHASE
    // levelOne:    pre link function is called on element instance
    // levelTwo:    pre link function is called on element instance
    // levelThree:  pre link function is called on element instance

    // POST-LINK PHASE (Notice the reverse order)
    // levelThree:  post link function is called on element instance
    // levelTwo:    post link function is called on element instance
    // levelOne:    post link function is called on element instance

 

概要

忆起上面的解析大家得以描述一下那些函数的区分以及使用情状:

Compile 函数

在ng创立原始dom实例以及开创scope实例在此之前,使用compile函数能够更改原有的dom(template
element)的生产,

能够运用于当供给转变多个element实例,唯有二个template
element的情事
,ng-repeat正是1个最好的例子,它就在是compile函数阶段改变原来的dom生成多少个原始dom节点,然后各种又生成element实例.因为compile只会运维贰遍,所以当你必要变更加多个element实例的时候是足以拉长品质的.

template
element以及有关的特性是做为参数字传送递给compile函数的,然而此时候scope是不可能用的:

上边是函数样子:

复制代码代码如下:

/**
    * Compile function
    * 
    * @param tElem – template element
    * @param tAttrs – attributes of the template element
    */
    function(tElem, tAttrs){

 

        // …

    };

 

Pre-link 函数

采取pre-link函数能够运作一些事情代码在ng执行完compile函数之后,不过在它全数子指令的post-link函数将要执行从前.

scope对象以及element实例将会做为参数字传送递给pre-link函数:

上面是函数样子:

复制代码代码如下:

/**
    * Pre-link function
    * 
    * @param scope – scope associated with this istance
    * @param iElem – instance element
    * @param iAttrs – attributes of the instance element
    */
    function(scope, iElem, iAttrs){

 

        // …

    };

 

Post-link 函数

动用post-link函数来进行工作逻辑,在那一个等级,它曾经知道它具有的子指令已经编写翻译完成而且pre-link以及post-link函数已经执行完结.

那就是被认为是最安全以及暗中同意的编写制定工作逻辑代码的原因.

scope实例以及element实例做为参数传递给post-link函数:

上边是函数样子:

复制代码代码如下:

/**
    * Post-link function
    * 
    * @param scope – scope associated with this istance
    * @param iElem – instance element
    * @param iAttrs – attributes of the instance element
    */
    function(scope, iElem, iAttrs){

 

        // …

    };

 

参考于:http://www.jb51.net/article/58229.htm

相关文章