1、基本概念javascript
做用域是一個指向應用模型的對象,至關於MVVM中的ViewModel,能綁定數據(屬性)和行爲(方法),能監控表達式和傳遞事件,是實現雙向綁定的基礎,是應用在 HTML (視圖) 和 JavaScript (控制器)之間的紐帶,是鏈接視圖和控制器的一個特殊的JavaScript對象。html
做用域是一個樹型層次結構,與DOM標籤平行,有根做用域,多個子做用域,子做用域下又有子做用域。全部的應用都有一個 $rootScope,它做用在 ng-app 指令包含的全部 HTML 元素中。$rootScope 可做用於整個應用中。是各個 controller 中 scope 的橋樑。用 rootscope 定義的值,能夠在各個 controller 中使用。ng-app 指令能夠產生一個根做用域以外,一些 指令會建立新的子做用域,而且進行原型繼承,如 ng-repeat、ng-include、ng-switch、ng-view、ng-controller, 另外,用 scope: true 和 transclude: true 建立自定義 directive也會產生新做用域。java
做用域變量性質,有局部變量和所有變量之分,全局變量能夠在方法,或者閉包內引入,而局部變量只能在定義的方法內使用,其餘方法引用不到,$rootscope至關於所有變量,不該在 $rootScope附加太多的業務邏輯數據(全局),而是用控制器顯示的建立 $scope對象來管理本身相關的邏輯和數據(局部)。angularjs
做用域繼承性,子做用域自動繼承父做用域的屬性和方法,若是本身有就用本身的同名屬性和方法。有以下內部關係ajax
scope.$parent :指向scope的父做用域api
scope.$$childHead:指向scope的第一個子做用域數組
scope.$$childTail:指向scope的最後一個子做用域閉包
scope.$$nextSibling:指向scope的下一個相鄰做用域app
scope.$$prevSibling:指向scope的上一個相鄰做用域框架
例子:
<html> <head> <title>Angular JS</title> </head> <body> <h2>AngularJS Sample</h2>
<!--綁定ng-app產生$rootscope,還有產生一個當前做用域$scope(shapeController),這裏產生兩個做用域-->
<!--message和type都顯示本身的--> <div ng-app="mainApp" ng-controller="shapeController"> <p>{{message}} <br/> {{type}} </p>
<!--產生一個子做用域(circleController)-->
<!--message顯示本身的,type沒定義,就顯示繼承過來的type--> <div ng-controller="circleController"> <p>{{message}} <br/> {{type}} </p> </div>
<!--產生另外一個平行子做用域(squareController)-->
<!--message和type都顯示本身的,雖然和根做用域有繼承關係--> <div ng-controller="squareController"> <p>{{message}} <br/> {{type}} </p> </div> </div> <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js"></script> <script> var mainApp = angular.module("mainApp", []); //父控制器,產生父做用域 mainApp.controller("shapeController", function($scope) { $scope.message = "In shape controller"; $scope.type = "Shape"; }); //子做用域,沒type,用父做用域的type mainApp.controller("circleController", function($scope) { $scope.message = "In circle controller"; }); //另外一個平行子做用域,有type用本身的type mainApp.controller("squareController", function($scope) { $scope.message = "In square controller"; $scope.type = "Square"; }); </script> </body> </html>
2、做用域上的$watch()、$apply()方法
一、watch()
用於監聽模型變化,當模型發生變化,它會提示你的。
表達式: $watch(watchExpression, listener, objectEquality);
其參數:
watchExpression:監聽的對象,它能夠是一個angular表達式如'name',或函數如function(){return $scope.name}。
listener:當watchExpression變化時會被調用的函數或者表達式,它接收3個參數:newValue(新值), oldValue(舊值), scope(做用域的引用)。
objectEquality:是否深度監聽,若是設置爲true,它告訴Angular檢查所監控的對象中每個屬性的變化. 若是你但願監控數組的個別元素或者對象的屬性而不是一個普通的值, 那麼你應該使用它。
$scope.name = 'hello'; var watch = $scope.$watch('name',function(newValue,oldValue, scope){ console.log(newValue); console.log(oldValue); }); $timeout(function(){ $scope.name = "world"; },1000);
在後臺顯示world,1秒後,會變成hello,$timeout內部會觸發$scope.$apply()
二、$apply()
用於傳播模型的變化,若是一些javascript方法,如setTimeout,調用了AngularJS 函數以後,必須調用$apply。
$scope.test = function() { setTimeout(function () { $scope.$apply(function () { $scope.user = "hello"; }); }, 2000); }
不能寫成下邊的代碼,這樣不能實現雙向數據綁定。
$scope.test = function() { setTimeout(function () { $scope.user = "hello"; }, 2000); }
3、做用
一、提供了觀察者能夠監聽數據模型的變化
二、能夠將數據模型的變化通知給整個 App
三、能夠進行嵌套,隔離業務功能和數據
四、給表達式提供上下文執行環境
4、$socpe的生命週期
scope的生命週期處理主要包含如下幾個階段:
一、建立: AngularJS啓動時,會使用 $injector建立一個根做用域,將做用域傳進相應的控制器或指令中
注意: AngularJS除了ng-controller和ng-repeat指令會建立本身的子做用域,通常不會建立本身的 $scope
二、連接(註冊觀察者): AngularJS運行時,指令會建立本身的做用域,全部的 $scope對象都會連接到視圖上,經過註冊 $watch函數來獲取數據變化通知
三、模型狀態改變:更新模型狀態必須發生在scope.$apply方法中才會被觀察到。Angular框架封裝了$apply過程,無需咱們操心。
四、更新: AngularJS經過在頂層 $scope對象執行事件循環,每一個自做用域都會執行本身的髒值檢測($digest),每一個監控函數會檢查變化,若是檢測到變化,則 $scope對象觸發指定的回調函數
五、銷燬: 當再也不須要子做用域時,$socpe上能夠經過使用 $destoy()方法銷燬做用域,回收資源。