摘要:因為在里面是基于原型進行繼承的。事實上注入后,即提供了一個,可以在這個上面綁定屬性和方法。當使用語法的時候,事實上是綁定到了的對象上面。注意這個地方執行順序是從子元素開始再到父元素的。即在執行階段前確保執行完畢。
Controller As
angular .module("app", []) .controller("DemoController", DemoController); function DemoController() { this.name = "XL"; this.sayName = function() { return this.name; } }{{vm.name}}
在js部分書寫控制器的時候,更像是在寫構造函數,然后在view層實例化一個ViewModule。那么在view里面可以直接調用掛載在這個vm上的屬性和方法。
這樣的寫法的好處就是避免在嵌套的controller里面使用$parent去獲取父controller里面的方法或值。因為在angular里面scope是基于原型進行繼承的。
{{name}}angular .module("app") .controller("parentController", parentController) .controller("childController", childController); //都使用的推斷式注入 function parentController($scope) { $scope.name = "XL"; } function childController($scope) { $scope.name = "xl"; }{{name}}
最后在視圖里面輸出"XL", "xl"。如果我要獲取的是父控制器里面的屬性值,那么我只能$scope.$parent去獲取,嵌套的controller多了怎么辦- -,使用controller as可以有效的避免這個問題.
如果使用這種controller as的寫法的話,盡量避免在controller里面使用$scope,除非遇到$emit,$broadcase,$on, $watch。
function SomeController($scope, $log) { var vm = this; vm.title = "Some Title"; $scope.$watch("vm.title", function(current, original) { $log("vm.title was %s", original); $log("vm.title is now %s", current); }); }this vs $scope
angular .module("app", []) .controller("parentController", parentController); function parentController($scope) { this.sayName = function() { console.log("this"); } }
結果:
點擊BtnA后能輸出"this",
點擊BtnB后不輸出任何東西。
事實上:
當書寫Controller的時候,即在寫controller constructor,使用controller as語法,當在view里面實例化controller后(vm),this便指向這個實例化vm,然后就可以在view里面調用vm所擁有的屬性和方法。在本例中即vm所擁有的sayName()方法
如果
function parentController($scope) { this.sayName = function() { console.log("this"); } $scope.sayName = function() { console.log("$scope"); } }
在controller constructor里面定義$scope.sayName方法,那么點擊BtnB的時候可以輸出$scope。
事實上:
注入$scope后,即提供了一個model,可以在這個model上面綁定屬性和方法。那么在view里面聲明的controller里面可以訪問到。
綜上,在this上面掛載的方法其實是在controller constructor上面掛載的方法,必須要通過controller實例去訪問。在$scope上面掛載的方法是在模型上面掛載的,因為在directive的pre-link階段(見下面的compile vs link)是將$scope綁定到DOM上,因此可以直接在view層訪問綁定在$scope的方法。
除此之外,this和$scope另外一個區別就是指向的問題:
log "this" and $scope
- parent scopelog "this" and $scope
- child scope
然后僅僅在parentController上面掛載方法:
$scope.logThisAndScope = function() { console.log(this, $scope); }
首先因為controller嵌套同時是在$scope上面掛載方法,因此父元素和子元素點擊都會輸出this和$scope的內容,在這個實例當中this的指向是不同的,一個是parentController另外一個是childController,$scope的指向是一樣的,同時指向的是綁定在id為parentBox的DOM內的$scope。
The problem with controllerAs in Directives當使用controllerAs語法的時候, controller scope事實上是綁定到了controller的this對象上面。但是在平時我們書寫directive的時候會創建獨立的作用域。
app.directive("someDirective", function() { return { scope: { oneWay: "@", twoWay: "=", expr: "&" } } })
接下來我們創建一個擁有獨立作用域,有自己的控制器的directive。
app.directive("someDirective", function() { return { scope: {}, controller: function() { this.name = "Pascal"; }, controllerAs: "ctrl", template: "{{ctrl.name}}" } })
但是,如果這個name屬性是一個可以和父作用域共享的呢?當然我們立馬想到的是
app.directive("someDirective", function() { return { scope: { name: "=" }, .... } })
如果外部的name屬性發生變化并不會立即反應到內部的controller的this對象上。在1.2版本里面處理這種情況就是使用$scope服務上掛載的$watch方法去監聽name屬性的變化。
app.directive("someDirective", function() { return { scope: { name: "=" }, controller: function($scope) { this.name = "Pascal"; $scope.$watch("name", function(newValue){ this.name = newValue; }.bind(this)); //這個地方要注意this的指向 } } })bindToController
1.3版本里面directive出現了一個新的配置對象bindToController,顧名思義綁定到controller上面,當directive使用獨立作用域以及controllerAs語法的時候,而且bindToController這個值被設置為true的時候,這個組件的屬性都被綁定到controller上了而不是scope上面。
這意味著,當controller被實例化后,獨立作用域上綁定屬性的初始值都可以通過this對象來訪問到,未來這個屬性的值發生變化后都能被檢測的到。
app.directive("someDirective", function () { return { scope: { name: "=" }, controller: function () { this.name = "Pascal"; }, controllerAs: "ctrl", bindToController: true, template: "{{ctrl.name}}" }; });
1.4版本的語法升級:
在1.3版本bindToController為boolen值,在1.4版本中為一個對象,即如果想將獨立作用域上的值綁定到controller上面,可以直接在bindToController這個對象上進行配置。
app.directive("someDirective", function () { return { scope: {}, bindToController: { someObject: "=", someString: "@", someExpr: "&" }, controller: function () { this.name = "Pascal"; }, controllerAs: "ctrl", template: "complie vs link{{ctrl.name}}{{ctrl.someObject}}" }; }); //如果父作用域里面的someObject屬性發生變化,會隨時反應到這個directive的template里面。
Angularjs在處理directive時,取決于自身的compile和link參數定義的規則:
當定義directive的時候同時定義了complie,pre-link,post-link3個參數的時候
Hello {{XL}} Hello {{Sugar}}
var app = angular.module("app", []); function createDirective(name) { return function() { return { restrict: "E", compile: function(tElem, tAttrs) { console.log(name + ": complie"); }, return { pre: function(scope, tElem, iAttrs) { console.log(name + ": pre link"); }, post: function(scope, tElem, iAttrs) { console.log(name + ": post link"); } } } } } app.directive("levelOne", createDirective("levelOne")); app.directive("levelTwo", createDirective("levelTwo")); app.directive("levelThree", createDirective("levelThree"))
結果:
angularjs一開始compile所有原生指令和自定義指令,complile階段還沒有綁定scope.link階段分為pre-link和post-link階段。
從結果看來compile階段和pre-link階段的順序一樣,但是post-link執行順序正好相反。
修改代碼:
function createDirective(name) { return function() { return { restrict: "E", compile: function(tElem, tAttrs) { console.log(name + ": complie =>" + 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()); } } } } }
結果:
現在再看下輸出的信息,特別是在pre-link階段,雖然和compile一樣輸出元素的順序是一樣的,但是元素中出現了屬性class="ng-binding",事實上在compile階段DOM元素仍然是最初html標記所創建的DOM元素,它是模板元素(template element)的實例元素(instance element).pre-link階段提供一個scope給這個實體,這個實體可以是全新的scope,繼承的scope或者是孤立的scope,取決于directive定義的scope屬性。
post-link階段:當實例元素初始化完成(compile階段)和綁定scope(pre-link階段)完成后就可以進行post-link(DOM)操作。注意這個地方執行順序是從子元素開始再到父元素的。即在level-one執行post-link階段前確保level-two.level-three執行完畢。
compile階段: /* * @param tElem - 模板元素 * @param tAttr - 模板元素的屬性 */ compile: function(tElem, tAttrs) { } pre-link階段 /* * @param scope - 連接于此的實例的scope * @param iElem - 實例元素 * @param iAttr - 實例元素的屬性 */ function (scope, iElem, iAttr) { } post-link階段 /* * @param scope - 連接于此實例的scope * @param iElem - 實例元素 * @param iAttr - 實例元素的屬性 */ function (scope, iElem, iAttr) { }where to use compile or link?
之前的寫法都是直接用link,默認進行了compile和pre-link的階段,在post-link里面就可以直接使用綁定在實例上的scope,ele,attrs。
如果在你的程序里面不需要使用scope,不需要$watch其他的值,僅僅提供模板實例的話,可以直接使用compile。這個時候你是不能對DOM有任何操作的。
除此之外,如果你不需要實例元iElem,那么也可以不用link函數。
但當你同時書寫compile和link函數(pre-link或者post-link)的時候,一定要在compile函數里面返回link函數,因為如果compile被定義的時候link屬性被忽略了。
參考資料bindToController
thisAndScope
the difference between compile and link
angularjs-style
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/78327.html
摘要:使用開發,很重要的一步是需要開發自定義的指令。接下來分幾個步驟記錄如何開發一個自定義的指令。對這個元素及其子元素進行變形之類的操作是安全的。鏈接函數鏈接函數負責注冊事件和更新。說明和是指令的關鍵部分,留在下一章中詳細討論。 使用Angularjs開發,很重要的一步是需要開發自定義的指令(custom directives)。接下來分幾個步驟記錄如何開發一個自定義的指令。 目錄: 指令...
摘要:基于原型的繼承性視圖存在嵌套的時候,內層的是可以繼承到外層的數據的。這者的區別就是在中繼承了中的作用域。通過監聽某個的是否發生變化來觸發相應的。第三個屬性值,當為規定的是比較對象的值,而不是引用。這樣可以非常好的將一些可服用的代碼抽離出來。 scope基于原型的繼承性 視圖存在嵌套的時候,內層的controller是可以繼承到外層的controller數據的。 scope在angula...
摘要:雖然這些東西都是非常棒的,但是它們都不是實現延遲加載所必需的東西。我們通過的配置對象中的屬性就可以實現延遲加載。單元測試的技巧把改成是全局依賴并不意味著你應該從控制器中刪除它。因為在單元測試中,你只會加載這一個控制器而非整個應用模塊。 原文鏈接:http://michalzalecki.com/lazy-load-angularjs-with-webpack/ 隨著你的單頁應用擴大,...
摘要:異步加載各個組件就很有必要。在這里我就以為框架來進行異步加載說明。而為了將服務進行異步加載我們不能用普通的或者。而需要調用或者如果采用進行編譯打包的話就需要的支持,這樣可以對進行拆分打包,達到異步加載的目的。 ui-route相比于angularjs的原生視圖路由更好地支持了路由嵌套,狀態轉移等等。隨著視圖不斷增加,打包的js體積也會越來越大,比如我在應用里面用到了wangeditor...
摘要:本文針對的讀者具備性能優化的相關知識雅虎條性能優化原則高性能網站建設指南等擁有實戰經驗。這種機制能減少瀏覽器次數,從而提高性能。僅會檢查該和它的子,當你確定當前操作僅影響它們時,用可以稍微提升性能。 搬運自: http://atian25.github.io/2014/05/09/angular-performace/ 不知不覺,在項目中用angular已經半年多了,踩了很多坑...
閱讀 2882·2021-09-28 09:36
閱讀 3608·2021-09-27 13:59
閱讀 2484·2021-08-31 09:44
閱讀 2278·2019-08-30 15:54
閱讀 2352·2019-08-30 15:44
閱讀 1180·2019-08-30 13:45
閱讀 1223·2019-08-29 18:38
閱讀 1207·2019-08-29 18:37