AngularJs concepts詳解及範例程式碼_AngularJS

來源:互聯網
上載者:User

原版地址:http://code.angularjs.org/1.0.2/docs/guide/concepts

繼續。。

一、總括

本文主要是angular組件(components)的概覽,並說明他們如何工作。列表如下:

  1. statup - 依舊是hello world...改為Hello Kitty!
  2. runtime - 介紹angular的runtime
  3. scope - view與contorller的紐帶(神馬glue...膠)
  4. controller - app的行為(application behavior)
  5. model - app的資料
  6. view - 使用者所看到的東東
  7. directives - HTML的文法擴充
  8. filters - 根據使用者的本地格式,格式化資料
  9. injector - 載入我們的app(依賴管理之類)
  10. module - 配置injector
  11. $ - angular的命名空間(namespace)

二、啟動(Startup)

下面描述angular是如何啟動的(參考圖表與下面的例子):

1. 瀏覽器載入HTML,將HTML標籤轉換為DOM對象;

2. 瀏覽器載入angular.js的指令碼;

3. Angular等待DOMContentLoaded事件;

4. Angular尋找ng-app這個用於指定應用邊界範圍的directive;

5. 如果ng-app有指定module(也許是ng-app=”SomeApp”),將被用作配置$injector;

6. $injector用於建立$compile服務(service)以及$rootScope;

7. $compile服務用作“編譯”(有點像遍曆,然後做一點神秘的事情)DOM,並將其與對應的$rootScope串連。

8. ng-init 這個directive在對應的scope中建立name屬性並對其賦予”Kitty”值;

9. 將“{{name}}”的值插入(interpolates)到運算式中,最終顯示”Hello Kitty!”。

 

<!DOCTYPE html><html lang="zh-cn" ng-app><head>  <meta charset="UTF-8">  <title>Hello Kitty!</title>  <style type="text/css">    .ng-cloak {      display: none;    }  </style></head><body><div ng-init="name='Kitty'">Hello {{name}}!</div><script src="../angular-1.0.1.js" type="text/javascript"></script></body></html>

由於今晚跟別人討論一些東西,所以進度緩慢。。。又是那句。。。現在已經是夜深了。。。Angular,廣告之後見!

==============================================

廣告完畢。。。繼續

三、Runtime

 

  這圖表和後面的例子,描述了angular如何通過瀏覽器event-loop(所有的時間處理函數,以及timer執行的函數,會排在一個queue結構中,利用一個無限的迴圈,不斷從queue中取出函數來執行,這個就是event-loop。來自http://wiki.nodejs.tw/nodejs_from_scratch/javascript-yunodejs/2-1-event-loop)來進行互動。

  1. 瀏覽器event-loop等待事件到來。事件來自於使用者互動(DOM events)、timer事件(setTimeout)、network事件(服務端響應,XHR之類);

  2. 事件回呼函數開始執行。這裡進入javascript上下文(context)。這回呼函數可以修改DOM結構。

  3. 當回呼函數執行完畢後,瀏覽器退出javascript context,根據DOM的改變來重繪視圖。

  Angular通過建立自己的事件處理迴圈(event processing loop),修改了一般的javascript流(flow)。這將Javascript分割成傳統的和Angular的執行內容(execution context)。只要是在Angular execution context 裡面執行的操作,都擁有angular data-binding、異常處理(exception handling)、屬性監視(property watching)等能力。我們可以通過在javascript使用$apply(),進入Angular execution context。但要記住一點,在大多數(angular的)地方(如controllers、services),處理事件的directive會為你調用$apply。手動調用$apply的情境,一般是當你實現自訂事件處理函數,或者處理第三方庫的回調的時候。

  1. 通過調用scope.$apply(stimulusFn)進入angular execution context。stimulusFn就是我們想在angular execution context中執行的函數(含scope作為參數)或者angular合法的運算式。

  2. Angular執行stimulusFn,這通常會改變應用的狀態(application state)。

  3. Angular進入$digest loop。這個loop由一個處理$evalAsync queue 和處理$watch list兩個更小的迴圈組成。$digest loop會在model穩定之前保持迭代,即$evalAsync queue為空白,而且$watch list沒有檢測到任何變化。

  4. $evalAsync queue被用作安排必須跳出當前堆疊框架(堆疊框架指的是在堆棧中為當前正在啟動並執行函數分配的地區(或空間)。傳入的參數、返回地址(當這個函數結束後必須跳轉到該返回地址。譯註:即主調函數的斷點處)以及函數所用的內部儲存單元(即函數儲存在堆棧上的局部變數)都在堆疊框架中。http://book.51cto.com/art/200804/70915.htm C.1.1  堆疊框架)之外,但在瀏覽器視圖繪製之前的工作。這通常是通過使用setTimeout(0)來實現。但setTimeout(0)這方法,會導致緩慢,或者在每個事件處理完畢後,瀏覽器繪製視圖時,出現視圖閃爍(angular有沒有去解決這個問題?如何解決?)。

  5. $watch list是有可能在最近一次迭代中被修改的運算式的集合。如果(model)發生了改變,那麼$watch 函數會被調用,從而達到對特定的DOM重新賦值的目標。

  6. 一旦Angular $digest loop 完成了(之前3提到的情況),離開angular和javascript的context後,瀏覽器緊跟著就會去重繪DOM,以響應變化。

  下面解釋例子“Hello Kitty”(-_-!)是如何在使用者在文字框輸入文本時實現資料繫結(data-binding)效果。

  1. 編譯階段(compilation phase):

    a) ng-model和input directive在<input>中版定keydown事件監聽器。

    b) {{name}}預留位置(interpolation,不知道怎麼翻譯)(運算式)設定一個$watch以便在name發生改變時有所響應。

  2. 執行階段(runtime phase):

    a) 在inut控制項中按下”X”按鈕,讓瀏覽器觸發一個keydown事件;

    b) input directive捕捉到文字框值的改變,然後調用$apply(“name = ‘X';”),在angular execution context中更新應用的model。

    c) Angluar將 “name = ‘X';”應用在model中。(model發生改變)

    d) $digest loop開始

    e) $watch list檢測到name的值被改變了,然後再次解析{{name}}運算式,然後更新DOM。

    f) Angulart退出(angular) execution context,再依次退出keydown事件以及javascript execution context;

    g) 瀏覽器重繪視圖,更新字元。

<!DOCTYPE html><html lang="zh-cn" ng-app><head>  <meta charset="UTF-8">  <title>Hello Kitty!</title>  <style type="text/css">    .ng-cloak {      display: none;    }  </style></head><body>  <input ng-model="name" class="ng-cloak"/>  <p>Hello {{name}}!</p><script src="../angular-1.0.1.js" type="text/javascript"></script></body></html>

四、Scope

  scope的是負責檢測model的變化,並作為運算式的執行內容(execution context)。Scope是在一個類似於DOM結構的階層中嵌套的(據之前瞭解,劃分可能跟controller有關)。(詳情查看individual directive documentation,看看哪個directive會建立新的scope)

  下面的例子展示”name”這個運算式的值是根據它依賴(所屬)的scope決定的,而且還包含了值尋找的方式(類似Js的範圍鏈,自己沒有就找老爸要)。

<!DOCTYPE HTML><html lang="zh-cn" ng-app><head>  <meta charset="UTF-8">  <title>scope</title>  <style type="text/css">    .ng-cloak {      display: none;    }  </style></head><body><div class="ng-cloak" ng-controller="ControllerA">  Hello {{name}}!;</div><div class="ng-cloak" ng-controller="ControllerB">  Hello {{name}}!;  <div class="ng-cloak" ng-controller="ControllerC">    Hello {{name}}!;    <div class="ng-cloak" ng-controller="ControllerD">      Hello {{name}}!;    </div>  </div></div><script src="../angular-1.0.1.js" type="text/javascript"></script><script type="text/javascript">  function ControllerA($scope) {    $scope.name = 'Kitty';  }  function ControllerB($scope) {    $scope.name = 'Lcllao';  }  function ControllerC($scope) {    $scope.name = 'Jeffrey';  }  function ControllerD($scope) {  }</script></body></html>

五、Controller


<!DOCTYPE HTML><html lang="zh-cn" ng-app><head>  <meta charset="UTF-8">  <title>Controller</title>  <style type="text/css">    .ng-cloak {      display: none;    }  </style></head><body><div class="ng-cloak" ng-controller="ControllerA">  Hello {{name}}!  <button ng-click="doIt()">DoIt!!</button></div><script src="../angular-1.0.1.js" type="text/javascript"></script><script type="text/javascript">  function ControllerA($scope) {    $scope.name = 'Kitty';    $scope.doIt = function() {      $scope.name = "Handsome";    };  }</script></body></html>

  Controller是在view背後的代碼(-_-!)。它的職責是構建model,並通過回呼函數,將其(model)推送到view中。View是當前scope到template(HTML)的映射(翻譯得有點勉強...)。Scope是指揮model到view以及向controller發送event的紐帶。

  Controller與view分離是很重要的,因為:

1.Controller是寫在javascript中的。Javascript是命令式的(imperative)。命令(imperative)是描述應用程式行為的一個好方法。Controller不應該包含任何顯示資訊(的邏輯)(DOM引用或者HTML片段)

2.View模版是寫在HTML裡的。HTML是聲明式的。聲明式(的HTML)是描述UI的好方法。View不應該包含任何行為。

3.由於Controller不知道自己需要對應哪一個View,使得一個Controller可以(間接)使用多個View。這對於re-skinning(更換皮膚?)、其他裝置特定的視圖(例如手機與案頭)還有代碼的可測性是很重要的。 

六、Model

  Model,可以理解為資料對象。它被用作與模版結合,以產生視圖。為了將model寫入到視圖中,model必須被scope所引用。與很多其他架構不一樣,angular對model沒有任何限制與要求。不需要額外添加class,也不需要通過特殊的特權方法去訪問或者改變model。Model的資料類型,可以是原始的類型(string、number……),可以是索引值對象({a:1,b:2}),也可以是函數(function() {…})。簡要地說,angular的model只需要是一個普通的javascript對象。

七、View

  view是使用者所能看到的東西。view誕生於模版。它與model結合,最終呈現為瀏覽器DOM。Angular採取一個對於其他很多模版系統來說,很不一樣的方式去呈現View。

其他模版引擎:很多模版引擎,是通過建立帶有特殊標記的HTML字串來實現的。通常這些模版標記破壞了HTML的文法,這意味著不能通過一般的HTML編輯器去編輯代碼(這個嘛…)。模版字串傳入模版引擎,與資料合併。最終產生HTML字串。這些字串一般通過.innerHTML的方式寫入DOM中,促使瀏覽器呈現模版內容。當資料發生改變時,這個過程需要一次又一次地重複。模版的粒度與DOM更新的粒度一致。這粒的關鍵,是模版系統處理字串。

Angular:Angular模版的不同之處,在於它是基於DOM的而不是基於字串的。模版依然需要在HTML中寫入一些字串,但依舊是HTML(不是通過在裡面嵌入模版)。瀏覽器把HTML轉換為DOM,然後DOM成為了compiler(angular的模版引擎)的輸入。Compiler尋找directives,依次在model中設定watches。得出的結果,是一個一直更新的view,不需要重新拼接model與template。model成為了view的唯一資料來源(single source of truth)。

 八、Directives

  Directive是一個行為(例如之前文章的例子“躲貓貓”)或DOM轉換(自訂標籤,裡麵包含一組DOM),將其名稱放在屬性、標籤名、class名裡面都可以觸發該directive。Directive允許你以聲明的方式擴充HTML的標籤。

  下面的例子,還有一些疑問。就是$render如何觸發@_@

<!DOCTYPE HTML><html lang="zh-cn" ng-app="myDirective"><head>  <meta charset="UTF-8">  <title>directive</title>  <style type="text/css">    .ng-cloak {      display: none;    }  </style></head><body ng-controller="MyCtrl"><div ng-model="content" contenteditable="true">My Little Dada</div><pre class="ng-cloak">modelValue = {{content}}</pre><button ng-click="reset()">reset(change model)</button><script src="../angular-1.0.1.js" type="text/javascript"></script><script type="text/javascript">  angular.module("myDirective",[])      .directive("contenteditable",function() {        return {          require:'ngModel',          link:function (scope, element, attr, ngModel) {            function setVal() {              ngModel.$setViewValue(element.text());            }            // veiw -> model            element.bind("keyup",function() {              scope.$apply(setVal);            });            // model -> view            ngModel.$render = function(val) {              console.log("render running");              element.html(val);            };            //init            setVal();          }        }      }  ).controller("MyCtrl",function($scope) {        $scope.reset = function() {            $scope.content = "My Little Dada";        };      });</script></body></html>

九、Filters

  Filters 扮演一個資料轉換(格式化)的角色。通常他們是與地區有關的,不同地區也許會有不同的輸出格式。他們在追隨了Unix過濾器的精神與類似的文法:|  (pipe)

<!DOCTYPE HTML><html lang="zh-cn" ng-app><head>  <meta charset="UTF-8">  <title>filter</title>  <style type="text/css">    .ng-cloak {      display: none;    }  </style></head><body><div ng-init="list = ['百度B','搜狗S','360','3SB']">  數字格式化: 1233211234567 -> {{1233211234567|number}}<br/>  數組過濾,然後通過json格式輸出: <input ng-model="myFilterText" type="text"/><br/>  {{list|filter:myFilterText|json}}<br/></div><script src="../angular-1.0.1.js" type="text/javascript"></script></body></html>

 十、Modules and the Injector

  Injector是一個服務定位器。每一個Angular應用,都會有一個單獨的injector。Injector提供一個通過名稱尋找對象執行個體的途徑。Injector會在內部cache中保持所有對象執行個體,所以重複調用相同的名稱時,返回的都是同一個對象執行個體。如果對象不存在,那麼它會請求執行個體工廠(instance factory)去建立一個新執行個體。

  Module是一個配置injector的執行個體工廠的方法,被稱為”provider”。 

 // Create a module  var myModule = angular.module('myModule', [])     // Configure the injector  myModule.factory('serviceA', function() {  return {  // instead of {}, put your object creation here  };  });     // create an injector and configure it from 'myModule'  var $injector = angular.injector('myModule');     // retrieve an object from the injector by name  var serviceA = $injector.get('serviceA');     // always true because of instance cache  $injector.get('serviceA') === $injector.get('serviceA');//true

  但是injector的真正牛X的地方在於它可以用於調用方法和”instantiate” type。這個美妙的特性是允許method和types請求他們所依賴的資源,而不是尋找他們。

 // You write functions such as this one.  function doSomething(serviceA, serviceB) {  // do something here.  }     // Angular provides the injector for your application  var $injector = ...;     ///////////////////////////////////////////////  // the old-school way of getting dependencies.  var serviceA = $injector.get('serviceA');  var serviceB = $injector.get('serviceB');     // now call the function  doSomething(serviceA, serviceB);   //上面是傳統的老方法~下面是angular說自己的牛X方法  ///////////////////////////////////////////////  // the cool way of getting dependencies.  // the $injector will supply the arguments to the function automatically  $injector.invoke(doSomething); // This is how the framework calls your functions

  注意,我們唯一需要寫的,就是我們的function,在function的arguments中列出方法依賴的資源即可!當angular調用function時,他會使用”call”方法,自動填滿function agruments。

  留意下面的例子中是如何在constructor中列出依賴的。當ng-controller執行個體化controller時,將自動提供所依賴的資源。沒有必要去建立、尋找、建立injector引用來載入依賴資源。

<!DOCTYPE HTML><html lang="zh-cn" ng-app="timeExample"><head>  <meta charset="UTF-8">  <title>injector</title>  <style type="text/css">    .ng-cloak {      display: none;    }  </style></head><body><div ng-controller="ClockCtrl" class="ng-cloak">  Current time is : {{time.now}}</div><script src="../angular-1.0.1.js" type="text/javascript"></script><script type="text/javascript">  angular.module("timeExample", []).factory("myClock", function ($timeout) {    var time = {};    (function tick() {      time.now = new Date().toString();      $timeout(tick, 1000);    })();    return time;  });  /**   *   * @param $scope   * @param myClock 這裡自動插入了依賴的myClock!!   * @constructor   */  function ClockCtrl($scope,myClock) {    $scope.time = myClock;  }</script></body></html>

十一、Angular Namespace

為了防止名稱衝突,angular會在object的名稱中加入首碼$。請不要在代碼中使用$首碼以避免衝突。(-_-!! )

以上就是關於AngularJS concepts 的資料整理,後續繼續添加相關文章,謝謝大家對本站的支援!

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.