angular.js指令中的controller、compile與link函數(shù)的不同之處
前言
算了算用angualrjs去做開發(fā)也有兩個(gè)月了,但做為一個(gè)菜鳥,難免會(huì)被大神吊打(這里有一個(gè)悲傷的故事...)。某天一位前端大神問我:你知道angular指令中的controller,compile,link函數(shù)有什么不同?然后我就一臉懵逼了....于是決定深入的去探究下。
今天我們來一起了解一下它們有什么不同的地方:
先看一段示例代碼
var ag = angular.module("myApp",[]); ag.controller("myCtrl",["$rootScope",function($rootScope){ }]); ag.directive("order",function(){ return{ restrict:"AE", controller:function($scope, $element, $attrs, $transclude) { console.log("controller"); }, compile:function(tElement, tAttrs, transclude){ console.log("compile"); return{ pre:function(scope, iElement, iAttrs, controller){ console.log("pre") }, post:function(scope, iElement, iAttrs, controller){ console.log("post") } } }, link:function(scope, iElement, iAttrs, controller){ console.log("link") } } });
我們可以看到什么order指令中寫了controller, complie, link函數(shù);我們可以思考一下上面會(huì)輸出一下什么來.
從上面的輸出結(jié)果我們可以得出兩個(gè)結(jié)論:
- 他們的執(zhí)行順序不同,最先執(zhí)行的是complie函數(shù) ; 然后是controller函數(shù),然后是pre函數(shù),最后是post函數(shù).
- link函數(shù)沒有執(zhí)行.
首先我們來解釋第一個(gè)問題;看下圖
從圖中我們可以看到整個(gè) AngularJs 的生命周期分為兩個(gè)階段:
第一個(gè)階段是編譯階段:
在編譯階段,AngularJS會(huì)遍歷整個(gè)HTML文檔并根據(jù)JavaScript中的指令定義來處理頁(yè)面上聲明的指令。每一個(gè)指令的模板中都可能含有另外一個(gè)指令,另外一個(gè)指令也可能會(huì)有自己的模板。當(dāng)AngularJS調(diào)用HTML文檔根部的指令時(shí),會(huì)遍歷其中所有的模板,模板中也可能包含帶有模板的指令.一旦對(duì)指令和其中的子模板進(jìn)行遍歷或編譯,編譯后的模板會(huì)返回一個(gè)叫做模板函數(shù)的函數(shù)。我們有機(jī)會(huì)在指令的模板函數(shù)被返回前,對(duì)編譯后的DOM樹進(jìn)行修改。
ag.directive("order",function(){ return{ restrict:"AE", compile:function(tELe ,tAttrs,transcludeFn){ //進(jìn)行編譯后的dom操作 return{ pre:function(scope, iElement, iAttrs, controller){ // 在子元素被鏈接之前執(zhí)行 // 在這里進(jìn)行Dom轉(zhuǎn)換不安全 }, post:function(scope, iElement, iAttrs, controller){ // 在子元素被鏈接之后執(zhí)行 } } } } })
第二個(gè)階段是鏈接階段:
鏈接函數(shù)來將模板與作用域鏈接起來;負(fù)責(zé)設(shè)置事件監(jiān)聽器,監(jiān)視數(shù)據(jù)變化和實(shí)時(shí)的操作DOM.鏈接函數(shù)是可選的。如果定義了編譯函數(shù),它會(huì)返回鏈接函數(shù),因此當(dāng)兩個(gè)函數(shù)都定義了時(shí),編譯函數(shù)會(huì)重載鏈接函數(shù).(解釋上面的結(jié)論2)
var ag = angular.module("myApp",[]); ag.controller("myCtrl",["$rootScope",function($rootScope){ }]); ag.directive("order",function(){ return{ restrict:"AE", controller:function($scope, $element, $attrs, $transclude) { console.log("controller"); }, link:function(scope, iElement, iAttrs, controller){ console.log("link") } } });
上面指令執(zhí)行時(shí);會(huì)輸出:
我們可以看到controller函數(shù)先執(zhí)行,然后是link函數(shù).但是鏈接階段會(huì)執(zhí)行controller,link函數(shù);那么他們有什么不同;我們?cè)谑裁辞闆r該用哪個(gè)?
答案是:
指令的控制器和link函數(shù)可以進(jìn)行互換。控制器主要是用來提供可在指令間復(fù)用的行為,但鏈接函數(shù)只能在當(dāng)前內(nèi)部指令中定義行為,且無法在指令間復(fù)用.link函數(shù)可以將指令互相隔離開來,而controller則定義可復(fù)用的行為。
實(shí)際使用的一些建議:
如果我們希望將當(dāng)前指令的API暴露給其他指令使用,可以使用controller參數(shù),否則可以使用link來構(gòu)造當(dāng)前指令元素的功能性。如果我們使用了scope.$watch()或者想要與DOM元素做實(shí)時(shí)的交互,使用鏈接會(huì)是更好的選擇。
到這里:我們應(yīng)該有一點(diǎn)了解這三者有什么差異了吧?其實(shí)這個(gè)問題考的就是我們對(duì)AngularJs生命周期的了解.
最后我們用一個(gè)實(shí)際例子來看一下AngularJs的生命周期:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body ng-app="myApp" ng-controller="myCtrl"> <div parent> <div child></div> </div> <script src="../plugins/angularjs/angular.src.js"></script> <script> var ag = angular.module("myApp",[]); ag.controller("myCtrl",["$rootScope",function($rootScope){ }]); ag.directive("parent",function(){ return{ restrict:"AE", controller:function($scope, $element, $attrs, $transclude) { console.log("parent controller"); }, compile:function(tElement, tAttrs, transclude){ console.log("parent compile"); return{ pre:function(scope, iElement, iAttrs, controller){ console.log("parent pre") }, post:function(scope, iElement, iAttrs, controller){ console.log("parent post") } } } } }); ag.directive("child",function(){ return{ restrict:"AE", controller:function($scope, $element, $attrs, $transclude) { console.log("child controller"); }, compile:function(tElement, tAttrs, transclude){ console.log("child compile"); return{ pre:function(scope, iElement, iAttrs, controller){ console.log("child pre") }, post:function(scope, iElement, iAttrs, controller){ console.log("child post") } } } } }); </script> </body> </html>
結(jié)果如圖:
可以參照上面的angularjs生命周期圖來理解.
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
Angular實(shí)踐之將Input與Lifecycle轉(zhuǎn)換成流示例詳解
這篇文章主要為大家介紹了Angular實(shí)踐之將Input與Lifecycle轉(zhuǎn)換成流示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02AngularJS中的API(接口)簡(jiǎn)單實(shí)現(xiàn)
本文主要介紹AngularJS API(接口),這里對(duì)AngularJS API的知識(shí)做了詳細(xì)講解,并附簡(jiǎn)單代碼實(shí)例,有需要的小伙伴可以參考下2016-07-07深入理解node exports和module.exports區(qū)別
下面小編就為大家?guī)硪黄钊肜斫鈔ode exports和module.exports區(qū)別。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-06-06簡(jiǎn)單講解AngularJS的Routing路由的定義與使用
這篇文章主要介紹了AngularJS的Routing路由的定義與使用,講解了when()和otherwise()兩個(gè)相關(guān)的常用方法,需要的朋友可以參考下2016-03-03AngularJs自定義服務(wù)之實(shí)現(xiàn)簽名和加密
AngularJS 是一個(gè) JavaScript 框架,它可以通過 <script> 標(biāo)簽添加到 HTML 頁(yè)面。這篇文章主要介紹了AngularJs自定義服務(wù)之實(shí)現(xiàn)簽名和加密的相關(guān)資料,需要的朋友可以參考下2016-08-08AngularJS實(shí)現(xiàn)與Java Web服務(wù)器交互操作示例【附demo源碼下載】
這篇文章主要介紹了AngularJS實(shí)現(xiàn)與Java Web服務(wù)器交互操作的方法,結(jié)合實(shí)例形式較為詳細(xì)的分析了AngularJS前臺(tái)ajax提交與javascript后臺(tái)處理的完整流程與實(shí)現(xiàn)技巧,并附帶demo源碼供讀者下載參考,需要的朋友可以參考下2016-11-11AngularJs用戶登錄問題處理(交互及驗(yàn)證、阻止FQ處理)
這篇文章主要為大家詳細(xì)介紹了AngularJs用戶登錄問題處理,包括交互及驗(yàn)證、阻止FQ處理,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10詳解webpack+es6+angular1.x項(xiàng)目構(gòu)建
這篇文章主要介紹了詳解webpack+es6+angular1.x項(xiàng)目構(gòu)建, 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-05-05深入學(xué)習(xí)JavaScript的AngularJS框架中指令的使用方法
這篇文章主要介紹了深入學(xué)習(xí)JavaScript的AngularJS框架中指令的使用方法,指令的使用是Angular入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2016-03-03