在Angular 1.2以后的版本中檩小,對于嵌套Controller的$scope處理就一直是一個很大的坑鳄炉,這部分主要得益于JavaScript語言級對繼承機制(原型繼承)杜耙。
本文主要分析Angular對于嵌套Controller作用域的另外一種解決方法,使用controller as 語法進行處理拂盯。
上篇為$scope的示例分析,下篇為controller as的示例分析泥技。
$scope的傳統(tǒng)寫法示例
假設我們在有3個Controller進行嵌套,打印出同一個變量,使用$scope的代碼是
controller.js
angular.module('app')
.controller('MainCtrl', function ($scope) {
$scope.title = "第一層";
})
.controller('AnotherCtrl', function ($scope) {
$scope.title = "第二層";
})
.controller('YetAnotherCtrl', function ($scope) {
$scope.title = "第三層";
})
與之對應的view代碼則為
view.html
<div ng-controller="MainCtrl">
{{ title }}
<div ng-controller="AnotherCtrl">
{{ title }}
<div ng-controller="YetAnotherCtrl">
{{ title }}
</div>
</div>
</div>
則HTML的頁面結(jié)果就是
<div ng-controller="MainCtrl" class="ng-scope ng-binding">
第一層
<div ng-controller="AnotherCtrl" class="ng-scope ng-binding">
第二層
<div ng-controller="YetAnotherCtrl" class="ng-scope ng-binding">
第三層
</div>
</div>
</div>
$scope的繼承機制
繼承
如當?shù)谌龑拥腨etAnotherCtrl不在自己的$scope內(nèi)對title變量做賦值操作珊豹,則$scope.title會指向上一層的AnotherCtrl中的$scope中進行調(diào)用簸呈,這里有一個向上尋找的過程,很類似Java中的多態(tài)實現(xiàn)(但只是類似)店茶。
故修改controller.js,注釋刪除掉內(nèi)部兩個ctrl的賦值語句蜕便。
controller.js
angular.module('app')
.controller('MainCtrl', function ($scope) {
$scope.title = "第一層";
})
.controller('AnotherCtrl', function ($scope) {
// $scope.title = "第二層";
})
.controller('YetAnotherCtrl', function ($scope) {
// $scope.title = "第三層";
})
則對應的view輸出怎么會變?yōu)?/p>
<div ng-controller="MainCtrl" class="ng-scope ng-binding">
第一層
<div ng-controller="AnotherCtrl" class="ng-scope ng-binding">
第一層
<div ng-controller="YetAnotherCtrl" class="ng-scope ng-binding">
第一層
</div>
</div>
</div>
YetAnotherCtrl與AnotherCtrl因為在自己的$scope中未對title屬性做復制,則會一層一層向父類$scope去調(diào)用贩幻,最后在MainCtrl中發(fā)現(xiàn)了title的并進行調(diào)用轿腺。
調(diào)用父類
回到最初如果3個Ctrl分別對title鍵值做出了賦值,我們需要顯式的在第三層中調(diào)用第一層的title值需要怎么做呢丛楚?
controller.js
angular.module('app')
.controller('MainCtrl', function ($scope) {
$scope.title = "第一層";
})
.controller('AnotherCtrl', function ($scope) {
$scope.title = "第二層";
})
.controller('YetAnotherCtrl', function ($scope) {
$scope.title = "第三層";
})
view.html
<div ng-controller="MainCtrl">
{{ title }}
<div ng-controller="AnotherCtrl">
{{ title }}
{{$parent.title}}
<div ng-controller="YetAnotherCtrl">
{{ title }}
{{$parent.title}}
</div>
</div>
</div>
我們需要通過$parent去直接操作當前$scope的父$scope去顯示其內(nèi)部的值族壳,根據(jù)以上代碼則會顯示如下的html結(jié)果
<div ng-controller="MainCtrl" class="ng-scope ng-binding">
第一層
<div ng-controller="AnotherCtrl" class="ng-scope ng-binding">
第二層 第一層
<div ng-controller="YetAnotherCtrl" class="ng-scope ng-binding">
第三層 第二層
</div>
</div>
</div>
終極版
最后,如果我們?nèi)サ舻诙拥膖itle賦值語句將controller.js改成
angular.module('app')
.controller('MainCtrl', function ($scope) {
$scope.title = "第一層";
})
.controller('AnotherCtrl', function ($scope) {
// $scope.title = "第二層";
})
.controller('YetAnotherCtrl', function ($scope) {
$scope.title = "第三層";
})
那么剛才最終獲得HTML會變成什么樣呢趣些?
答案是
<div ng-controller="MainCtrl" class="ng-scope ng-binding">
第一層
<div ng-controller="AnotherCtrl" class="ng-scope ng-binding">
第一層 第一層
<div ng-controller="YetAnotherCtrl" class="ng-scope ng-binding">
第三層 第一層
</div>
</div>
</div>
主要原理如下
- 當?shù)谌龑覻etAnotherCtrl調(diào)用$scope.title的時候仿荆,因為YetAnotherCtrl中又對應的操作故最后獲取的是自己所賦值的字符串;
- 當?shù)谌龑覻etAnotherCtrl調(diào)用$parent.title坏平。則$parent會先去查找Another中的$scope是否有title值拢操,結(jié)果是沒有的,故會再向上找舶替,找到MainCtrl中的title值令境。
- 當?shù)诙覣notherCtrl調(diào)用$scope.title的時候,同理因為本身沒有故會向上查找顾瞪;
小結(jié)
$scope相當于給所有的controller提供了可繼承共享的上下文舔庶,很靈活,副作用是不好排錯陈醒、子類調(diào)用父類的代碼變得非常的不好理解栖茉,并且原型繼承天生有很多坑。
相關(guān)的文章可見官方一篇介紹$scope的專題:
https://github.com/angular/angular.js/wiki/Understan:ding-Scopes