ANGULAR之中,$STATE $WATCH $SCOPE $ROOTSCOPE 分別是什麼?
1.背景介紹
AngularJs是一個用於設計動態web應用的結構框架,使得開發現代的單一頁面應用程式變得更加容易。而且 能夠簡化我們的工作流程, 讓我們只專心於業務邏輯和資料的處理。$scope $rootScope $watch 和 $state就是裡面的 幾個方法,今天著重跟大家討論一下這幾個方法。
2.知識剖析
$scope——Scope(作用域) 是應用在 HTML (檢視) 和 JavaScript (控制器)之間的紐帶。Scope 是一 個物件,有可用的方法和屬性。 Scope 可應用在檢視和控制器上。$scope 的使用貫穿整個 Angular App 應用,它與數 據模型相關聯,同時也是表示式執行的上下文。 有了 $scope 就在檢視和控制器之間建立了一個通道,基於作用域檢視在 修改資料時會立刻更新 $scope, 同樣的 $scope發生改變時也會立刻重新渲染檢視。
$scope 的生命週期
- $scope 的生命週期有4個階段:
- 建立:控制器或者指令建立時, Angular 會使用 $injector 建立一個新的作用域,然後在控制器或指令執行時, 將作用域傳遞進去。
- 連結:Angular 啟動後會將所有 $scope 物件附加或者說連結到檢視上,所有建立 $scope 物件的函式也會被附 加到檢視上。 這些作用域將會註冊當 Angular 上下文發生變化時需要執行的函式.也就是 $watch 函式, Angular 通過這些函式或者何時開始事件迴圈。
- 更新:一旦事件迴圈開始執行,就會開始執行自己的髒值檢測.一旦檢測到變化,就會觸發 $scope 上指定的回撥函式。
- 銷燬:通常來講如果一個 $scope 在檢視中不再需要, 需要對其進行清理。
$rootscope
$rootscope——每一個Angular應用都會有一個 $rootScope。這個 $rootScope 是最頂級的scope,它 對應著含有 ng-app 指令屬性的那個DOM元素。 如果頁面上沒有明確設定 $scope ,Angular 就會把資料和函式都繫結 到這裡。Angular 應用啟動並生成檢視時,會將根 ng-app 元素與 $rootScope 進行繫結.$rootScope 是所有 $scope 的 最上層物件, 可以理解為一個 Angular 應用中得全域性作用域物件。
$watch
相信使用過angularjs的同學都知道,ng中有個比較重要的特點,叫做雙向繫結,那麼這個雙向繫結是如何 實現的呢? 當我們在對繫結的name屬性進行修改的時候,angular內部的$digest迴圈級會執行一次, 他執行的內容是檢 查我們的 $scope作用域的內容與上次執行$digest迴圈的時候是否有變化,若有變化就執行$watch()方法繫結的處理函式。 從而 達到了監聽作用域屬性的效果。
$watch的幾個引數
- watchExpression;需要監控的表示式;
- listener,處理函式,函式引數如下 function(newValue,oldValue, scope);
- objectEquality,是否深度監聽,如果設定為true,它告訴Angular檢查所監控的物件中每一個屬性的變化. 如果你希 望監控陣列的個別元素或者物件的屬性而不是一個普通的值, 那麼你應該使用它。
$state
在ajax技術發展普及之後,因為其不會留下歷史記錄方便瀏覽器訪問和對於seo不友好的特點,一個新技術 應運而生: 路由,$state就是路由中的一項服務。
$state.go()
$state.go()方法可以產生與a連結一樣的效果,可以將此方法繫結給一個button按鈕, 然後在按鈕的點選 事件中執行 $state.go(),就可以跳轉到相應的頁面。
$stateparams
$stateParams是一個物件,包含 url 中每個引數的鍵/值。$stateParams可以為控制器或者服務提供 url 的各個部分。 注意:$stateParams必須與一個控制器相關,並且$stateParams中的“鍵/值”也必須事先在那個控制器的url屬性中有定義。
3.常見問題
$watch的深度監聽是什麼?
$watch的深度監聽有什麼優缺點?
4.解決方案
$watch的深度監聽是什麼?
$watch在對待原始型別和引用型別會有不同的處理方式,這就要首先說一說$watch函式的第三個引數。在前面的例子中, 我們知道,$watch函式有接收兩個引數,第一個引數是需要監視的物件,第二個引數是在監視物件發生變化時需要呼叫 的函式, 實際上$watch還有第三個引數,它在預設情況下是false。在預設情況下,即不顯示指明第三個引數或者將其 指明為false時, 我們進行的監視叫做“引用監視”。引用監視的原詞的“reference watch”,它的意思是隻要監視的 物件引用沒有發生變化, 就不算它發生了變化。如果我們將$watch的第三個變數設定為true,那麼此時我們進行的監視 叫做“全等監視”,原詞是“equality watch”。
$watch的深度監聽有什麼優缺點?
前面我們說到,只要$watch的物件有一點風吹草動,watch的深度監聽馬上就跳出來; 既然全 等監視這麼好,那麼我們為什麼不直接用全等監視呢?當然,任何事情都有好的壞的兩個方面,全等監視固然是好, 但 是它在執行時需要先遍歷整個監視物件,然後在每次$digest(髒檢查機制)之前使用angular.copy()將整個物件深拷貝一遍然後在執行 之後用angular.equal()將前後的物件進行對比。對效能優化來說這可不是很友好。
5.編碼實戰
6.擴充套件思考
$watch髒檢測原理
scope通過$watch方法向this. watchers陣列中新增watcher物件(包含watchFn,listenerFn,valueEq,last四個屬性)。每當$digest迴圈被觸發時,它會 遍歷watchers陣列中新增watcher物件(包含watchFn,listenerFn,valueEq,last四個屬性)。每當$digest迴圈被觸發時, 它會遍歷watchers陣列中新增watcher物件(包含watchFn, listenerFn, valueEq, last 四個屬性)。每當$digest迴圈被 觸發時,它會遍歷watchers陣列,執行watcher中的watchFn,獲取當前scope上某屬性的值(一個watcher對應scope上一 個被監聽屬性),然後去同watcher中的last(上一次的值)做比較,若兩值不相等,就執行listenerFn。
7.參考文獻
參考資料:http://www.cnblogs.com/sitemanager/p/3513827.html
—— 『AngularJS』理解$Scope
參考資料:https://www.jianshu.com/p/3398f1d19320
—— 關於angularJS的$watch的 一些小用法
參考資料:http://yuankeqiang.lofter.com/post/8de51_1454f93
—— angularJS中的$watch方法監聽作用域
8.更多討論
怎麼定義或修改$rootScope作用域的屬性和方法?
$stateParams如果沒有用url接收會怎樣?
9.互動提問
$rootScope是否可以替代$scope? 答:是可以替代的,但是不建議這樣用,因為這樣使用就相當於js中的全域性變數,定義過多會導致全域性汙染。
$state.params和$stateParams的區別? 答:$state.params裡的params是自己定義的,可以寫成listParams,optionparams等 $stateParams是angular定義的固定寫法;
什麼時候使用$watch?
答;angular會為我們自動執行$watch,當指令中有獨立作用域,或者在非同步函式中,改變的資料不在angular的執行上下文,就需要手動呼叫apply 來觸發digest去執行watch