AngularJS는 놀랍습니다 . 이를 통해 매우 의미 있고 재사용 가능한 구성 요소를 만들 수 있습니다. 어떤 의미에서는 웹 구성 요소의 궁극적인 선구자로 생각할 수 있습니다.
맞춤 지침 작성 방법에 대한 좋은 기사와 책이 많이 있습니다. 반대로 pre-link
와 pre-link
는 말할 것도 없고 compile
과 link
함수의 차이점도 포함되어 있다는 점은 매우 흥미롭습니다. code>포스트 링크 code> 기능. compile
和link
函数的不同,更不要说pre-link
与post-link
函数了。
大多数教程都简洁的提及到compile
函数主要被用在AngularJS内部并且建议你只使用link
函数这可以覆盖大多数自定义指令使用场景。
因此,跟谁我,在本文的最后,您将确切知道这些功能是什么以及何时应该使用它们。
This article assumes that you already know what an AngularJS directive is. If not, I would highly recommend reading the AngularJS developer guide section on directives first.
在我们开始之前,让我们先来分解AngularJS如何处理指令。
当浏览器渲染一个页面时,它一定会去阅读HTML标签,创建DOM并且在DOM准备就绪时广播事件。
当你使用<script></script>
在你的代码页中引入AngulaJS时,AngularJS监听那事件当它一旦收到事件,它开始遍历DOM,查询一个有ng-app
属性的标签。
当这个标签被查找到,AngularJS开始使用该特定元素作为起点处理DOM。因此,如果在html
元素上设置ng-app
属性,AngularJS将开始处理从html
元素开始的DOM。
从这时起,AngularJS递归地查询所有的子元素,寻找对应于你的AngularJS应用程序中定义的指令的模式。
AngularJS如何处理元素取决于实际的指令定义对象。你定义了一个compile
函数,一个link
函数或者两者。或者你可以定义一个pre-link
函数和一个post-link
函数来代替link
函数。
那么,所有这些功能之间有什么区别,以及为什么或什么时候应用它们?
跟紧我...
为了解释差异,我将使用一些希望易于理解的示例代码。
考虑下面的HTML标记:
<level-one> <level-two> <level-three> Hello {{name}} </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'));
目的很简单:使AngularJS处理三个嵌套的指令,每个指令都有自己的compile
,pre-link
,post-link
函数去log一行文本保证我们能够辨识它们。
这应该使我们能够首先了解AngularJS处理指令后发生的情况。
以下是控制台中输出的屏幕截图:
自己尝试一下,仅仅打开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
这清晰的证明了AngularJS是如何第一编译所有指令在把他们link他们是scope之前,并且在link阶段被分解为了pre-link
,post-link
阶段
注意到compile
与pre-link
函数调用顺序是相同的但是post-link
与他们刚好相反。
所以在这一点上我们已经可以清楚地识别出不同的阶段,那么compile
与pre-link
有什么区别了?他们执行的顺序是相同的,那为什么要把他们分开?
为了深入研究,让我们更新JavaScript,以便在每个函数调用期间输出元素的DOM:
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()); } } } } } }
注意console.log
行中的额外输出。没有其他更改,原始标记仍然使用。
以下是新添加的代码的输出截图:
再次,如果你想自己尝试一下,只需打开this plnkr并看看控制台。
打印出的DOM显示一些有趣的事:DOM在compile
与pre-link
阶段是不同的。
我们已经知道AngularJS在检测到DOM已经准备就绪时会处理DOM。
所以当AngularJS开始遍历DOM,它碰到<level-one></level-one>
元素并且了解到它在匹配我们定义的指令它有额外的动作需要执行
由于在evelOne
指令定义对象中定义了一个compile
컴파일
기능이 주로 AngularJS는 내부적으로 대부분의 사용자 지정 지시문 사용 시나리오를 처리할 수 있는 link
기능만 사용하는 것이 좋습니다. 따라서 이 글을 끝까지 읽으면 이러한 기능이 무엇인지, 언제 사용해야 하는지 정확히 알게 될 것입니다. #🎜🎜#이 글에서는 여러분이 AngularJS 지시문이 무엇인지 이미 알고 있다고 가정합니다. 그렇지 않다면 지시문에 대한 AngularJS 개발자 가이드 섹션을 먼저 읽어 보시기 바랍니다.
<script></script>
를 사용하면 AngularJS는 해당 이벤트를 수신한 후 Traverse를 시작합니다. ng-app
속성이 있는 태그에 대한 DOM 및 쿼리입니다. #🎜🎜##🎜🎜#이 태그가 발견되면 AngularJS는 해당 특정 요소를 시작점으로 사용하여 DOM 처리를 시작합니다. 따라서 html
요소에 ng-app
속성을 설정하면 AngularJS는 html
요소부터 DOM 처리를 시작합니다. #🎜🎜##🎜🎜# 이 시점부터 AngularJS는 모든 하위 요소를 재귀적으로 쿼리하여 AngularJS 애플리케이션에 정의된 지시문에 해당하는 패턴을 찾습니다. #🎜🎜##🎜🎜#AngularJS가 요소를 처리하는 방법은 실제 지시어 정의 개체에 따라 다릅니다. 컴파일
함수, 링크
함수 또는 둘 다를 정의합니다. 또는 링크
함수 대신 프리 링크
함수와 포스트 링크
함수를 정의할 수 있습니다. #🎜🎜##🎜🎜#그럼 이 모든 기능의 차이점은 무엇이며, 왜, 언제 적용해야 할까요? #🎜🎜##🎜🎜#Follow me...#🎜🎜#// 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 * * @param tElem - template element * @param tAttrs - attributes of the template element */ function(tElem, tAttrs){ // ... };
컴파일
, 프리 링크
, 포스트 링크
기능이 있어 텍스트 줄을 기록하여 식별할 수 있습니다. #🎜🎜##🎜🎜#이것은 AngularJS가 지시문을 처리한 후 어떤 일이 일어나는지 먼저 살펴보는 것입니다. #🎜🎜#/** * 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){ // ... };
사전 링크
, 사후 링크
단계#🎜🎜##🎜🎜#로 분류되는지 증명합니다. compile
과 pre-link
의 함수 호출 순서는 동일하지만 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){ // ... };
console.log
줄. 다른 변경 사항은 없으며 원래 마크업이 계속 사용됩니다. #🎜🎜#컴파일
및 사전 링크
단계에서 다릅니다. 의. #🎜🎜#<level-one></level-one>
요소를 발견하고 그것이 우리가 정의한 지시어와 일치하며 수행할 추가 작업이 있다는 것을 이해합니다. # 🎜🎜##🎜🎜#evelOne
지시문 정의 객체에 compile
함수가 정의되어 있으므로 이를 호출하고 해당 요소 DOM을 매개변수로 전달합니다# 🎜🎜##🎜🎜#자세히 살펴보면 이 시점에서 요소의 DOM은 원시 HTML 마크업을 사용하여 브라우저에서 원래 생성된 DOM입니다. #🎜🎜#在AngularJS中 original DOM 常被指代为template element,因此我个人钟意使用tElem
作为参数名,以代表template element。
一旦levelOne
指令的compile
函数已经运行,AngularJS递归地便利深层的DOM并对<level-two></level-two>
和<level-three></level-three>
元素执行同样的编译步骤。
在深入pre-link
函数之前,让我们先看一看post-link
函数
如果你创建的指令中只有link 函数,AngularJS将它当作post-link
函数,这也是我们先讨论它的原因。
在AngularJS向下传递DOM并运行所有编译compile
之后,它再次反向遍历并运行所有相关的post-link
函数。
DOM现在在相反的方向上遍历,因此post-link
函数按相反的顺序调用。所以,虽然相反的顺序几分钟前看起来很奇怪,但它现在开始变得非常有意义。
这个相反的顺序保证了在父元素的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
函数。
因此控制台输出有差异
在编写post-link
函数时,可以保证所有子元素的post-link
函数都已经执行。
在大多数情况下,这是非常有意义的,因此它是编写指令代码最常用的地方。
然而AngularJS提供了一个附加的钩子,the pre-link
函数,你可以在所有子元素执行post-link
函数之前执行你的代码。
值得重申的是:pre-link
函数能保证在所有子istance element执行post-link
前先执行。
因此,尽管post-link
函数以相反的顺序调用非常合理,但现在再次以原始顺序调用所有pre-link
函数是非常有意义的。
元素的pre-link
函数被保障在任意子元素的pre-link
与post-link
先执行
如果我们现在回顾原始输出,我们可以清楚地认识到发生了什么:
// 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
来实现在AngularJS创建它的实例之前和创建范围之前更改原始DOM(模板元素)。
虽然可以有多个元素实例,但只有一个模板元素。ng-repeat
指令是这种情况的一个很好的例子。这使得编译功能成为修改DOM的理想场所,以后应该将其应用于所有实例,因为它只会运行一次,因此如果要删除大量实例,则会极大地提高性能。
模板元素和属性作为参数传递给编译函数,但没有scope可用:
/** * Compile function * * @param tElem - template element * @param tAttrs - attributes of the template element */ function(tElem, tAttrs){ // ... };
使用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
函数执行逻辑,所有的子元素已经被编译并且所有子元素的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){ // ... };
위 내용은 AngularJS 지시문 컴파일 및 링크 기능에 대한 진실의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!