angular js自學筆記(二)——作用域1.0

作用域1.0

控制器與$scope


   瞭解作用域,首先要理解angular js的控制器。控制器的主要職責是初始化作用域實例,那麼問題來了,什麼是作用域實例呢?學過Java的人都知道,Java中可以將很多方法和需要的屬性封裝到一個類中,方便其他類調用,在我個人看來,angular js裏面就定義了一個scope類,而我們在html裏面使用ng-controller標籤(這個標籤是由指令(Directives)定義的)時,會自動創建一個scope類的實例。這裏就從angular js的運行來談,由於我之前的學習時針對的Java和c語言,所以就拿Java來做對比,在dom加載完後,瀏覽器發現ng-app標籤後,會先創建一個根作用域$root(這個root可以看成是Java中的類繼承的根類),然後看到了ng-controller,於是又創建一個$scope(此時的$scope完全繼承自$root,也就是說可以用$root的所有屬性),也就是說在一個標籤內的另一個標籤如果創建作用域,如果沒指明父作用域,那麼它們之間就有個繼承關係,說到這裏,再回到控制器來,它的職責有個亮點“初始化”,也就是說控制器其實就是用來給$scope的屬性賦值(這裏的值可爲數組,對象等,這個是js特有的特點)和方法

ng-repeat怎麼創建作用域

        ng-repeat我在第一次接觸時就喜歡上了它,因爲有了它,我可以很簡單的實現很多想法,它的作用是重複創建所在的標籤,這個時候問題又來了,它這個語法"XXX in XXXs"(後面那個就表示複數啊)按照我上面說的原則,對應每個XXX,都有個新變量要暴露給$scope,而又不能覆蓋之前的變量值,這個時候同名(XXX)的屬性怎麼創建作用域(屬性也有自己的作用域,因爲js的特點,屬性也可以爲對象等),angular js爲了解決這個問題,使用了一個叫“模型值”(model values)的東東,用以辨別同名的屬性作用域(也就是3個數字,如001)。



嘗試

        對於以上的學習,我做了如下的嘗試來驗證:

        test.html

  1. <span style="font-size:18px;"><html >  
  2. <head>  
  3.     <script type="text/javascript" src="angular.min.js"></script>  
  4.     <script type="text/javascript" src="test.js"></script>  
  5.     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />  
  6. </head>  
  7. <body ng-app ng-init="appName='app'">  
  8.     $root.appName={{appName}}  
  9.     <div ng-controller="aCtrl">  
  10.         <hr>  
  11.         控制器作用域<br>  
  12.         使用父作用域的appName:<input ng-model="appName">  
  13.         $root.appName:{{appName}}  
  14.           
  15.     <br/>對names進行ng-repeat,給集合每個元素創建一個叫a的屬性作用域  
  16.       <div ng-repeat="a in names">  
  17.         <br/>  
  18.         使用a獲取:{{a}}<br/>  
  19.         使用a.name獲取:{{a.name}}<br>  
  20.       </div>  
  21.     </div>  
  22. </body>  
  23. </html></span>  
        test.js
[javascript] view plaincopy
  1. <span style="font-size:18px;">var aCtrl = function($scope){  
  2.     $scope.names = [  
  3.         {name:"1"},  
  4.         {name:"2"},  
  5.     ];  
  6. };</span>  
       現在來看看瀏覽器的效果

   

       

        下面是ng-app($root)的作用域,  可以看到我定義的屬性appName。

     

        再來看ng-controller($scope)的作用域,它裏面也可以看到$root的appName,而且多了個屬性names(這是我通過js給$scope創建的屬性)

        下面再來看看ng-controller中通過ng-repeat創建的屬性作用域

        第一個屬性作用域,在裏面有父作用域中的appName和names,而且又多了個a的屬性,注意names集合中對象的值裏多了個我在js裏沒有定義的$$hashKey,這個東西應該就是model values。


        第二個屬性作用域也就大同小異了,可以看到唯一的區別就是$$hashKey的值


         既然子作用域可以用父作用域的值,那我就不免想到用子作用域更改值,會產生什麼影響,以下是改變後瀏覽器的變化

         因爲我的input標籤與appName實現了雙向數據綁定,可以看到我更改appName後,分割線上的{{appName}}無改變,而ng-controller($scope)中的{{appName}}改變了。


        來看看這個時候ng-app($root)的作用域,很明顯appName沒有改變,那麼ng-controller($scope)裏的appName爲什麼變了呢?

        帶着疑問,我又看了ng-controller($scope)的作用域,沒錯,裏面的appName改變了,再做了相關的查閱後,總結出一個原因:ng-controller生成的作用域創建了新的appName變量,而不是去修改$root中設定的appName的值,而如果想要修改,可以利用<input ng-model="$parent.appName">明確的引用父作用域來實現。

       
        以上是這篇筆記中的所有嘗試。

TIP

        anguler js中官方定義的屬性前都有個$符號,所以呢,我們創建自己的變量時就最好不要加$了,這樣也方便查看,然後Firefox有個查看angular js作用域的工具,叫做Angscope,很有用,我就拿它來驗證自己對作用域的猜想。

       sublime的一個快捷鍵,alt+shift+數字,可以實現分屏,蠻實用的。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章