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