作為初次接觸 AngularJS的新手,想要深層理解里面的內容短時間還是不可能的,所以標題寫了淺談字樣,以下內容是參考各位大神以及相關書籍整理加個人理解,出現錯誤的地方請大家指正。
$scope(作用域),為AngularJS中MVC的核心,整理起來很麻煩, 看着大神們發的一些文章對於$scope的理解,有些方面還是看不懂,作為新手,應該站在新手的位置上去思考,所以這篇文章的目的,就是讓我們這些新手初步理解$scope,懂得會用就可以了。
一、$scope概念及用法。
什么是作用域。
作用域是一個指向應用模型的對象。作用域有層次結構,有根作用域,多個子作用域,位置不同,作用不同。作用域能監控表達式和傳遞事件。應用在 HTML (視圖) 和 JavaScript (控制器)之間的紐帶。
談到AngularJS作用域之前,先熟悉下js中全局變量跟局部變量的差別。看下圖
var too="test"; if(true){//這是在塊中的定義,此時還是全局變量 var too="new test"; } alert(too=="new test");//return true; function test() { var too="old test";//這是在函數中的定義,此時是局部變量 } test(); alert(too=="new test");//return true;too並沒有改變
這里說明,全局變量可以在方法,或者閉包內引入,而局部變量只能在定義的方法內使用,其他方法引用不到,angular作用域跟變量性質相似。想深入了解js作用域鏈或者全局、局部變量關系,請參考湯姆大叔博客
http://www.cnblogs.com/TomXu/archive/2011/12/15/2288411.html 接下來看angular全局作用域和局部作用域區別用法:
angular中的$scope作用域可以根據需求,定義成一個變量或者是一個對象。
myApp.controller('myAppCtrl', function($scope){ //定義成變量 $scope.book = "Angular開發指南"; //定義成對象 $scope.book ={ name :'', author:'', pubTime:'' } })
全局作用域:
var myApp = angular.module('myApp', []); /* *run方法用於初始化全局的數據,僅對全局作用域起作用。 *這里的run方法只會在angular啟動的時候運行一次。 */ myApp.run(function($rootScope){ $rootScope.people ={ name:'小明', age:'12', tel:'12233333333' }; });
全局作用域是各個 controller 中 scope 的橋梁。用 rootscope 定義的值,可以在各個 controller 中使用。經常用於的場景在多個頁面切換,數據隨時綁定。(若是把數據綁定在$scope局部作用域是行不通的)。
局部作用域:
myApp.controller('myAppCtrl', function($scope){ $scope.book ={ name :'', author:'', pubTime:'' } }) myApp.controller('myAppCtrl1',function($scope,$rootScope){ console.log($scope.book.name);//undefined console.log($rootScope.people.name) //小明 })
二、$scope(作用域)特點
1.$scope提供了一些工具方法$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);
$apply()用於傳播模型的變化。AngularJS 外部的控制器(DOM 事件、外部的回調函數如 jQuery UI 空間等)調用了AngularJS 函數之后,必須調用$apply。
比如:
myApp.controller('myAppCtrl', function($scope){ $scope.user = ''; $scope.test = function() { setTimeout(function () { $scope.user = "hello"; }, 2000); } $scope.test1 = function() { $scope.user = 'world'; } $scope.test1(); $scope.test(); console.log($scope.user); })
上例解釋:
正常理解是:在后台顯示world,2秒后,會變成hello。
實際情況是:在后台顯示world,2秒后,不會成hello。
怎么才能讓user自動變化呢?修改一下。
$scope.test = function() { setTimeout(function () { $scope.$apply(function () { $scope.user = "hello"; }); }, 2000); }
這樣就可以了。。。。。。
2.$scope可以為一個對象傳播事件,類似DOM事件。舉例說明:
<!DOCTYPE html> <html lang="en" ng-app="myApp"> <head> <meta charset="UTF-8"> <title>demo</title> <script src="dist/angular-1.3.0.14/angular.js"></script> </head> <body> <div class="form" ng-controller="myAppCtrl"> <input type="button" value="提交" ng-click="submit()"> </div> <script type="text/javascript"> var myApp = angular.module('myApp', []); myApp.controller('myAppCtrl',function($scope){ $scope.submit = function(){ alert("提交成功!"); } }) </script> </body> </html>
3.$scope不僅是MVC的基礎,也是實現雙向數據綁定的基礎。作用域提供表達式執行上下文,比如說表達式{{username}}本身是無意義的。要與作用域$scope指定的username屬性中才有意義。舉個栗子:
<!DOCTYPE html> <html lang="en" ng-app="myApp"> <head> <meta charset="UTF-8"> <title>demo</title> <script src="dist/angular-1.3.0.14/angular.js"></script> </head> <body> <div class="form" ng-controller="myAppCtrl"> <input type="text" name="username" ng-model="username">{{username}} <input type="button" value="提交" ng-click="submit()"> </div> <script type="text/javascript"> var myApp = angular.module('myApp', []); myApp.controller('myAppCtrl',function($scope){ $scope.username = '小明同學'; $scope.submit = function(){ alert("提交成功!"); } }) </script> </body> </html>
其他幾點就不一一舉例說明了,做些實例應該就會理解了。
4.$scope是一個POJO(Plain Old JavaScript Object)。
5.$scope是一個樹型結構,與DOM標簽平行。
6.子$scope對象會繼承父$scope上的屬性和方法。
三、$scope(作用域)的作用。
在特點部分中,也明顯的看出來它的作用是怎樣的了,下面總結一下它的作用:
-
提供了觀察者可以監聽數據模型的變化
-
可以將數據模型的變化通知給整個 App
-
可以進行嵌套,隔離業務功能和數據
-
給表達式提供上下文執行環境
四、$scope(作用域)的生命周期。
1. 創建 - 更作用域會在應用啟動時通過注入器創建並注入。在模板連接階段,一些指令會創建自己的作用域。
2. 注冊觀察者 - 在模板連接階段,將會注冊作用域的監聽器。這也監聽器被用來識別模型狀態改變並更新視圖。
3. 模型狀態改變 - 更新模型狀態必須發生在scope.$apply方法中才會被觀察到。Angular框架封裝了$apply過程,無需我們操心。
4. 觀察模型狀態 - 在$apply結束階段,angular會從根作用域執行$digest過程並擴散到子作用域。在這個過程中被觀察的表達式或方法會檢查模型狀態是否變更及執行更新。
5. 銷毀作用域 - 當不再需要子作用域時,通過scope.$destroy()銷毀作用域,回收資源。
接下來,$scope(作用域)與控制器、指令等之間的聯系,在以后關於控制器、指令整理的文章解析,敬請期待。
(ps:本文中,有些實例是從大神發表的文章摘抄下來,如有雷同,莫怪莫怪!另外,文章中若出現不合理或錯誤的地方,請盡快聯系樓樓,謝謝啦~)