作用域是構成AngularJS應用的核心基礎,在整個框架中都被廣泛使用。作用域是視圖和控制器之間的膠水。在應用將視圖渲染並呈現個用戶之前,視圖中的模板和作用域進行連接,然後應用會對DOM進行設置以便將屬性變化通知給AngularJS。也就是說,作用域是應用狀態的基礎。基於動態綁定,我們可以依賴視圖在修改數據時立即更新$scope
,也可以依賴$scope
在其發生改變時立刻重新渲染視圖
- 以下方式會創建新的子作用域,並且進行原型繼承:
ng-repeat
ng-include
ng-switch
ng-view
ng-controller
scope:true
和transclude:true
創建directive
在創建子作用域後,關於屬性方法等的查找像js原型鏈繼承類似。如果子作用域中不存在該屬性,會在父作用域中查找,如果不存在,則在子作用域中創建該屬性。但是ng-repeat會對每一個迭代項item都會創建子作用域,子作用域也從父作用域進行原型繼承。但它還是會在子作用域中新建同名屬性,把item賦值給對應的子作用域的同名屬性
以下方式會創建獨立作用域,不會進行原型繼承:用scope: {…}創建directive,這樣創建的作用域被稱爲“隔離作用域”。默認情況下創建directive使用了scope:false,不會創建子作用域
如果一個
scope
不存在於元素上,那麼它將繼承它的父級scope<div ng-controller = "MyController"> <h1>{{clock}}</h1> </div>
在script腳本里編寫控制器函數
var app = angular.module('myapp',[]); app.controller("MyController",function($scope,$timeout){ var updateClock = function(){ $scope.clock = new Date(); $timeout(function(){ updateClock(); },1000) }; updateClock(); })
如果一個元素不是某個ng-app的一部分,那麼它不屬於任何scope。
AngularJS啓動並生成視圖時,會將根ng-app元素同 $rootScope 進行綁定。$rootScope
是所有 $scope
對象的最上層。$scope
對象就是一個普通的JavaScript對象,存在於AngularJS中的控制層。我們可以在其上隨意修改或添加屬性。 $scope
對象在AngularJS中充當數據模型,但與傳統的數據模型不一樣,$scope
並不負責處理和操作數據,它只是視圖和HTML之間的橋樑,它是視圖和控制器之間的膠水。$scope
的所有屬性都可以自動被視圖訪問到。
<div ng-controller='ParentController'>
<p>we can access :{{rootProperty}} and {{parentProperty}}</p>
<div ng-controller="ChildController">
<p>we can access: {{rootProperty}} and {{parentProperty}} and {{childProperty}}</p>
<p>{{fullSentenceFromChild}}</p>
</div>
</div>
添加控制器函數
var app = angular.module('myapp',[]);
//run訪問$rootScope屬性和方法
app.run(function($rootScope){
$rootScope.rootProperty = 'root scope';
})
app.controller('ParentController',function($scope){
$scope.parentProperty = 'partent scope';
})
app.controller('ChildController',function($scope){
$scope.childProperty = 'child scope';
$scope.fullSentenceFromChild = 'Same $scope:we can access:'+ $scope.rootProperty + 'and' + $scope.parentProperty + 'and' + $scope.childProperty;
})
運行結果如下
scope內部屬性
打開Chrome並導航到正在使用的一個angular應用程序,審查元素並打開開發者工具。我們知道$0
可以獲得最後一個選中的元素,$1
訪問前一個被選中的元素。在控制檯中輸入命令
angular.element($0).scope()
下面是該命令產生的屬性
$id
: scope的唯一標識符$root
: 根scope$parent
: 父級scope,如果scope ==scope.$root
則爲null$$childHead
: 第一個子scope,如果沒有則爲null$$childTail
: 最後一個子scope,如果沒有則爲null$$prevSibling
: 前一個相鄰節點scope,如果沒有則爲null$$nextSibling
: 後一個相鄰節點scope,如果沒有則爲null
scope與事件的傳播
使用scope可以綁定事件和發佈事件,angular中發送事件可以使用$emit
(向上發送事件)、$broadcast
(向下發送事件)$on
來綁定事件
<div ng-controller="parentCtrl">
<div ng-controller='selfCtrl'>
<span class='btn' ng-click='click()'>click me</span>
<div ng-controller='childCtrl'></div>
</div>
<div ng-controller='broCtrl'></div>
</div>
<script type="text/javascript">
var app = angular.module('myapp',[]);
app.controller('parentCtrl',function($scope){
$scope.$on('to-parent',function(e,d){
console.log('topartent'+d);
})
})
app.controller('selfCtrl',function($scope){
$scope.$on('to-child',function(e,d){
console.log('toChild+child'+d);
})
$scope.click = function(){
$scope.$broadcast('to-child','haha');
$scope.$emit('to-parent','hehe');
}
})
app.controller('childCtrl',function($scope){
$scope.$on('to-child',function(e,d){
console.log('toChild+child'+d);
})
})
app.controller('broCtrl',function($scope){
$scope.$on('to-child',function(e,d){
console.log('toChildbto'+d);
})
})
</script>
具體實現代碼請參看github scope與事件傳播
最後總結scope的特點
$scope
是一個普通的js對象(pojo)$scope
提供了一些工具方法,如$watch
、$apply
等$scope
是表達式的執行環境$scope
是一個樹形結構,與DOM標籤平行,並且能夠訪問父類的屬性和方法- 每一個Angular運行環境中都有根作用域,一般位於ng-app所定義的節點上
$scope
可以傳播書劍,類似DOM事件,可以向上傳播($emit
),也可以向下傳播($broadcast
)- 可以通過angular.element($0).scope()進行調試