1. 程式人生 > >關於AngularJS學習整理---淺談$scope(作用域) 新手必備!

關於AngularJS學習整理---淺談$scope(作用域) 新手必備!

  作為初次接觸 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(作用域)的作用。

  在特點部分中,也明顯的看出來它的作用是怎樣的了,下面總結一下它的作用:

  1. 提供了觀察者可以監聽資料模型的變化

  2. 可以將資料模型的變化通知給整個 App

  3. 可以進行巢狀,隔離業務功能和資料

  4. 給表示式提供上下文執行環境

四、$scope(作用域)的生命週期。

  

     1.  建立 - 更作用域會在應用啟動時通過注入器建立並注入。在模板連線階段,一些指令會建立自己的作用域。

    2.  註冊觀察者 - 在模板連線階段,將會註冊作用域的監聽器。這也監聽器被用來識別模型狀態改變並更新檢視。

    3.  模型狀態改變 - 更新模型狀態必須發生在scope.$apply方法中才會被觀察到。Angular框架封裝了$apply過程,無需我們操心。

    4.  觀察模型狀態 - 在$apply結束階段,angular會從根作用域執行$digest過程並擴散到子作用域。在這個過程中被觀察的表示式或方法會檢查模型狀態是否變更及執行更新。

    5.  銷燬作用域 - 當不再需要子作用域時,通過scope.$destroy()銷燬作用域,回收資源。

    接下來,$scope(作用域)與控制器、指令等之間的聯絡,在以後關於控制器、指令整理的文章解析,敬請期待。

  (ps:本文中,有些例項是從大神發表的文章摘抄下來,如有雷同,莫怪莫怪!另外,文章中若出現不合理或錯誤的地方,請儘快聯絡樓樓,謝謝啦~)