Maison  >  Article  >  interface Web  >  La vérité sur les directives AngularJS : compiler et lier les fonctions

La vérité sur les directives AngularJS : compiler et lier les fonctions

寻∝梦
寻∝梦original
2018-09-07 14:40:081215parcourir

AngularJS est génial et vous permet de créer des composants hautement sémantiques et réutilisables. Dans un sens, vous pouvez les considérer comme les précurseurs ultimes des composants Web.

Il existe de nombreux bons articles et livres sur la façon de rédiger des instructions personnalisées. Au contraire, il est très intéressant qu'il s'agisse de la différence entre les fonctions compile et link, sans parler des fonctions pre-link et post-link.

La plupart des tutoriels mentionnent succinctement que la fonction compile est principalement utilisée dans AngularJS et il est recommandé d'utiliser uniquement la fonction link qui peut couvrir la plupart des scénarios d'utilisation de directives personnalisées.

Alors suivez-moi, à la fin de cet article vous saurez exactement quelles sont ces fonctionnalités et quand vous devez les utiliser.

Cet article suppose que vous savez déjà ce qu'est une directive AngularJS. Sinon, je vous recommande fortement de lire d'abord la section du guide du développeur AngularJS sur les directives.

Comment AngularJS gère les directives

Avant de commencer, expliquons comment AngularJS gère les directives.

Lorsque le navigateur affiche une page, il doit lire les balises HTML, créer le DOM et diffuser les événements lorsque le DOM est prêt.

Lorsque vous utilisez <script></script> pour introduire AngulaJS dans votre page de codes, AngularJS écoute cet événement une fois qu'il reçoit l'événement, il commence à parcourir le DOM et recherche une balise avec l'attribut ng-app.

Lorsque cette balise est trouvée, AngularJS commence à traiter le DOM en utilisant cet élément spécifique comme point de départ. Ainsi, si vous définissez l'attribut html sur un élément ng-app, AngularJS commencera à traiter le DOM à partir de l'élément html.

À partir de ce moment, AngularJS interroge de manière récursive tous les éléments enfants, à la recherche de modèles qui correspondent aux directives définies dans votre application AngularJS.

La manière dont AngularJS gère les éléments dépend de l'objet de définition de directive réel. Vous définissez une fonction compile, une fonction link ou les deux. Ou vous pouvez définir une fonction pre-link et une fonction post-link au lieu de la fonction link.

Alors, quelles sont les différences entre toutes ces fonctionnalités, et pourquoi ou quand les appliquer ?

Suivez-moi...

Démonstration de code

Pour expliquer les différences, je vais utiliser un exemple de code qui, je l'espère, sera facile à comprendre.

Considérez le balisage HTML suivant :

<level-one>  
    <level-two>
        <level-three>
            Hello {{name}}         
        </level-three>
    </level-two>
</level-one>

et le JS suivant :

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'));

Le but est simple : faire en sorte qu'AngularJS gère trois directives imbriquées, une pour chacune Chaque commande possède ses propres fonctions compile, pre-link et post-link pour enregistrer une ligne de texte afin de garantir que nous pouvons les identifier.

Cela devrait nous permettre d'abord de comprendre ce qui se passe après qu'AngularJS ait traité la directive.

Sortie

Voici une capture d'écran de la sortie dans la console :
La vérité sur les directives AngularJS : compiler et lier les fonctions
Essayez-le vous-même, ouvrez simplement ce plnkr et prenez un regardez la sortie de la console

Démarrez l'analyse

La première chose à remarquer est l'ordre des appels de fonction

// 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

Cela prouve clairement comment AngularJS compile toutes les instructions avant les relier C'est avant la portée, et est décomposé en pre-link, post-link phase

dans la phase de liaison. Notez que l'ordre d'appel de la fonction de compile et pre-link est le même, mais. post-link est exactement le contraire d'eux.

Donc à ce stade, nous pouvons clairement identifier les différentes étapes, alors quelle est la différence entre compile et pre-link ? Ils s’exécutent dans le même ordre, alors pourquoi les séparer ?

Le DOM

Pour creuser plus profondément, mettons à jour le JavaScript pour afficher le DOM de l'élément lors de chaque appel de fonction :

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());
          }
        }
      }
    }
  }
}

Remarquez la sortie supplémentaire de la ligne console.log. Aucun autre changement, le balisage d'origine est toujours utilisé.

Sortie

Voici une capture d'écran de la sortie du code nouvellement ajouté :
La vérité sur les directives AngularJS : compiler et lier les fonctions

Encore une fois, si vous le souhaitez essayez-le vous-même, ouvrez simplement ce plnkr et jetez un œil à la console.

L'observation du DOM imprimé de

montre quelque chose d'intéressant : le DOM est différent aux étapes compile et pre-link.

Que se passe-t-il ici

Compilation

Nous savons déjà qu'AngularJS gère le DOM lorsqu'il détecte qu'il est prêt.

Ainsi, lorsque AngularJS commence à parcourir le DOM, il rencontre l'élément <level-one></level-one> et apprend qu'il correspond à la directive que nous avons définie et qu'il a des actions supplémentaires à effectuer

en raison du evelOne définition de la directive Il y a une fonction compile définie dans l'objet, elle est appelée et l'élément DOM correspondant est passé en paramètre

Si vous regardez bien, à ce stade, le DOM de l'élément est toujours le même tel que fourni à l'origine par le DOM du navigateur créé à l'aide du balisage HTML brut.

在AngularJS中 original DOM 常被指代为template element,因此我个人钟意使用tElem作为参数名,以代表template element。

一旦levelOne指令的compile函数已经运行,AngularJS递归地便利深层的DOM并对<level-two></level-two><level-three></level-three>元素执行同样的编译步骤。

Post-link

在深入pre-link函数之前,让我们先看一看post-link函数

如果你创建的指令中只有link 函数,AngularJS将它当作post-link函数,这也是我们先讨论它的原因。

在AngularJS向下传递DOM并运行所有编译compile之后,它再次反向遍历并运行所有相关的post-link函数。

DOM现在在相反的方向上遍历,因此post-link函数按相反的顺序调用。所以,虽然相反的顺序几分钟前看起来很奇怪,但它现在开始变得非常有意义。
La vérité sur les directives AngularJS : compiler et lier les fonctions

这个相反的顺序保证了在父元素的post-link函数运行时所有子元素的post-link函数已经运行。

所以当<level-one></level-one>post-link执行时,我们保证<level-two></level-two> <level-three></level-three>post-link函数已经执行。

这就是为什么它被认为是最安全和默认的添加指令逻辑的原因。

但是元素的DOM呢?这里为什么不同?

一单AngularJS已经调用了compile函数,它创建了一个对应模板元素的instance element并为instance提供一个scope。The scope可以为一个新的scope或者存在的一个,子scope或者隔离的scope,取决于相应指令定义对象的scope属性。

因此,在link发生时,实例元素和范围已经可用,并且它们被AngularJS作为参数传递给post-link函数。

因此控制台输出有差异

Pre-link

在编写post-link函数时,可以保证所有子元素的post-link函数都已经执行。

在大多数情况下,这是非常有意义的,因此它是编写指令代码最常用的地方。

然而AngularJS提供了一个附加的钩子,the pre-link函数,你可以在所有子元素执行post-link函数之前执行你的代码。

值得重申的是:
pre-link函数能保证在所有子istance element执行post-link前先执行。

因此,尽管post-link函数以相反的顺序调用非常合理,但现在再次以原始顺序调用所有pre-link函数是非常有意义的。

元素的pre-link函数被保障在任意子元素的pre-linkpost-link先执行
La vérité sur les directives AngularJS : compiler et lier les fonctions

回顾

如果我们现在回顾原始输出,我们可以清楚地认识到发生了什么:

// 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 function

使用compile来实现在AngularJS创建它的实例之前和创建范围之前更改原始DOM(模板元素)。

虽然可以有多个元素实例,但只有一个模板元素。ng-repeat指令是这种情况的一个很好的例子。这使得编译功能成为修改DOM的理想场所,以后应该将其应用于所有实例,因为它只会运行一次,因此如果要删除大量实例,则会极大地提高性能。

模板元素和属性作为参数传递给编译函数,但没有scope可用:

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

    // ...

};

Pre-link function

使用pre-link函数来实现当AngularJS已经编译子元素时,但在子元素的任何post-link函数被调用之前运行的逻辑。

scope,instance 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){

    // ...

};
Here you can see example code of official AngularJS directives that use a pre-link function.

Post-link function

使用post-link函数执行逻辑,所有的子元素已经被编译并且所有子元素的pre-link post-link已经执行。

所以post-link是被当作最安全和默认的位置放置你的代码。
scope,instance 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){

    // ...

};

最后,本篇文章到这就结束 (想看更多就到PHP中文网angularjs学习手册中学习),有问题的可以在下方留言提问

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn