Heim > Web-Frontend > js-Tutorial > Hauptteil

Die Wahrheit über AngularJS-Direktiven zum Kompilieren und Verknüpfen von Funktionen

寻∝梦
Freigeben: 2018-09-07 14:40:08
Original
1219 Leute haben es durchsucht

AngularJS ist großartig und ermöglicht Ihnen die Erstellung hochsemantischer und wiederverwendbarer Komponenten. In gewisser Weise kann man sie als die ultimativen Vorläufer von Webkomponenten betrachten.

Es gibt viele gute Artikel und Bücher darüber, wie man individuelle Anweisungen schreibt. Im Gegenteil, es ist sehr interessant, dass es sich um den Unterschied zwischen den Funktionen compile und link handelt, ganz zu schweigen von den Funktionen pre-link und post-link.

In den meisten Tutorials wird kurz und bündig erwähnt, dass die Funktion compile hauptsächlich in AngularJS verwendet wird, und es wird empfohlen, nur die Funktion link zu verwenden, die die meisten Verwendungsszenarien für benutzerdefinierte Anweisungen abdecken kann.

Folgen Sie mir also, am Ende dieses Artikels werden Sie genau wissen, was diese Funktionen sind und wann Sie sie verwenden sollten.

In diesem Artikel wird davon ausgegangen, dass Sie bereits wissen, was eine AngularJS-Direktive ist. Wenn nicht, würde ich Ihnen dringend empfehlen, zuerst den Abschnitt des AngularJS-Entwicklerhandbuchs über Direktiven zu lesen.

Wie AngularJS mit Direktiven umgeht

Bevor wir beginnen, erläutern wir, wie AngularJS mit Direktiven umgeht.

Wenn der Browser eine Seite rendert, muss er die HTML-Tags lesen, das DOM erstellen und Ereignisse übertragen, wenn das DOM bereit ist.

Wenn Sie <script></script> verwenden, um AngulaJS in Ihre Codepage einzuführen, wartet AngularJS auf dieses Ereignis. Sobald es das Ereignis empfängt, beginnt es mit der Durchquerung des DOM und sucht nach einem Tag mit dem Attribut ng-app.

Wenn dieses Tag gefunden wird, beginnt AngularJS mit der Verarbeitung des DOM unter Verwendung dieses spezifischen Elements als Ausgangspunkt. Wenn Sie also das html-Attribut für ein ng-app-Element festlegen, beginnt AngularJS mit der Verarbeitung des DOM beginnend mit dem html-Element.

Von diesem Zeitpunkt an fragt AngularJS alle untergeordneten Elemente rekursiv ab und sucht nach Mustern, die den in Ihrer AngularJS-Anwendung definierten Anweisungen entsprechen.

Wie AngularJS mit Elementen umgeht, hängt vom tatsächlichen Direktivendefinitionsobjekt ab. Sie definieren eine compile-Funktion, eine link-Funktion oder beides. Oder Sie können eine pre-link-Funktion und eine post-link-Funktion anstelle der link-Funktion definieren.

Was sind also die Unterschiede zwischen all diesen Funktionen und warum oder wann sollten sie angewendet werden?

Folgen Sie mir...

Code-Demonstration

Um die Unterschiede zu erklären, werde ich einen Beispielcode verwenden, der hoffentlich leicht zu verstehen ist.

Betrachten Sie das folgende HTML-Tag:

<level-one>  
    <level-two>
        <level-three>
            Hello {{name}}         
        </level-three>
    </level-two>
</level-one>
Nach dem Login kopieren

und ein bisschen 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'));
Nach dem Login kopieren

Der Zweck ist einfach: Lassen Sie AngularJS drei verschachtelte Anweisungen verarbeiten, jede mit ihrem eigenen The , compile und pre-link protokollieren eine Textzeile, um sicherzustellen, dass wir sie identifizieren können. post-link

Dies sollte es uns ermöglichen, zunächst zu verstehen, was passiert, nachdem AngularJS die Direktive verarbeitet hat.

Ausgabe

Hier ist ein Screenshot der Ausgabe in der Konsole:


Die Wahrheit über AngularJS-Direktiven zum Kompilieren und Verknüpfen von FunktionenProbieren Sie es selbst aus, öffnen Sie einfach diesen Plnkr und machen Sie einen Schauen Sie sich die Konsolenausgabe an

Starten Sie die Analyse

Das erste, was auffällt, ist die Reihenfolge der Funktionsaufrufe

// 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
Nach dem Login kopieren
Dies beweist deutlich, wie AngularJS alle Anweisungen zuerst kompiliert, bevor es sie verknüpft und sie sind vorher Bereiche und wurden in der Linkphase in die Phasen

, pre-link post-link

zerlegt. Beachten Sie, dass die Reihenfolge der Funktionsaufrufe von

und compile dieselbe ist, aber pre-link ist genau das Gegenteil davon. post-link

An dieser Stelle können wir also die verschiedenen Phasen klar identifizieren. Was ist also der Unterschied zwischen

und compile? Sie werden in der gleichen Reihenfolge ausgeführt. Warum also trennen? pre-link

Das DOM

Um tiefer zu graben, aktualisieren wir das JavaScript, um das DOM des Elements bei jedem Funktionsaufruf auszugeben:

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());
          }
        }
      }
    }
  }
}
Nach dem Login kopieren
Beachten Sie das Extra in der

-Zeilenausgabe. Keine weiteren Änderungen, das ursprüngliche Markup wird weiterhin verwendet. console.log

Ausgabe

Hier ist ein Screenshot der Ausgabe des neu hinzugefügten Codes:


Die Wahrheit über AngularJS-Direktiven zum Kompilieren und Verknüpfen von Funktionen

Noch einmal, wenn Sie möchten Probieren Sie es selbst aus. Öffnen Sie einfach dieses Plnkr und werfen Sie einen Blick auf die Konsole.

Die Betrachtung des gedruckten DOM von

zeigt etwas Interessantes: Das DOM unterscheidet sich in den Phasen

und compile. pre-link

Was passiert hier?

Kompilierung

Wir wissen bereits, dass AngularJS das DOM verarbeitet, wenn es erkennt, dass das DOM bereit ist.

Wenn AngularJS also beginnt, das DOM zu durchqueren, stößt es auf das

-Element und erfährt, dass es mit der von uns definierten Direktive übereinstimmt und aufgrund des <level-one></level-one> zusätzliche Aktionen ausführen muss

Direktivendefinition Es ist eine evelOne-Funktion im Objekt definiert, die aufgerufen wird, und das entsprechende Element-DOM wird als Parameter compile

übergeben. Wenn Sie genau hinschauen, ist das DOM des Elements an dieser Stelle immer noch das Dasselbe wie ursprünglich vom Browser bereitgestellt, erstellt mit rohem HTML-Markup.

在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函数按相反的顺序调用。所以,虽然相反的顺序几分钟前看起来很奇怪,但它现在开始变得非常有意义。
Die Wahrheit über AngularJS-Direktiven zum Kompilieren und Verknüpfen von Funktionen

这个相反的顺序保证了在父元素的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先执行
Die Wahrheit über AngularJS-Direktiven zum Kompilieren und Verknüpfen von Funktionen

回顾

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

// 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
Nach dem Login kopieren

总结

回想起来,我们可以如下描述不同的功能和用例:

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){

    // ...

};
Nach dem Login kopieren

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){

    // ...

};
Nach dem Login kopieren
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){

    // ...

};
Nach dem Login kopieren

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

Das obige ist der detaillierte Inhalt vonDie Wahrheit über AngularJS-Direktiven zum Kompilieren und Verknüpfen von Funktionen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage