歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

AngularJS開發指南3:Angular主要組成部分以及如何協同工作

AngularJS的主要組成部分是:

  • 啟動(startup) - 展示“hello world!”
  • 執行期(runtime) - AngularJS 執行期概覽
  • 作用域(scope) - 視圖和控制器的集合區
  • 控制器(controller) - 應用的行為
  • 模型(model) - 應用的數據
  • 視圖(view) - 用戶能看到的
  • 指令(directives) - 擴展HTML語法
  • 過濾器(filters) - 數據本地化
  • 注入器(injector) - 聚合你的應用
  • 模塊(module) - 配置注入器
  • $ - AngularJS的命名空間(namespace)

啟動

我們通過一個例子來講解啟動這個部分

 

<!doctype html>
<html ng-app>
  <head>
    <script src="http://code.angularjs.org/angular-1.1.0.min.js"></script>
  </head>
  <body>
    <p ng-init=" name='World' ">Hello {{name}}!</p>
  </body>
</html>


1.浏覽器載入HTML,然後把它解析成DOM樹。
2.浏覽器載入angular.js腳本。
3.AngularJS等到DOMContentLoaded事件觸發執行。
4.AngularJS尋找ng-app指令,這個指令指示了應用程序的邊界。
5.使用ng-app中指定的模塊來配置注入器($injector)。
6.注入器($injector)是用來創建“編譯服務($compile service)”和“根作用域($rootScope)”的。
7.編譯服務($compile service)是用來編譯DOM樹並把它鏈接到根作用域($rootScope)的,這裡的根作用域就是html。
8.ng-init指令將“World”賦給作用域裡的name這個變量。
9.作用域中的name與頁面上的{{name}}綁定,整個表達式變成了“Hello World”。

執行期

浏覽器的事件機制:
1.浏覽器的Event loop等待事件的觸發。所謂事件包括用戶的交互操作、定時事件、或者網絡事件(服務器的響應)。
2.事件觸發後,如果有綁定事件回調函數,那麼此函數就會被執行。此時會進入Javascript上下文。通常回調用來修改DOM結構。
3.一旦回調執行完畢,浏覽器就會離開Javascript上下文,並且根據DOM的修改重新渲染視圖。

而AngularJS通過使用自己的Event loop,改變了傳統的Javascript工作流。這使得Javascript的執行被分成原生部分和擁有AngularJS執行上下文的部分。只有在AngularJS執行上下文中運行的操作,才能享受到AngularJS提供的數據綁定,異常處理,資源管理等功能和服務。你可以使用 $apply()方法,從普通Javascript上下文進入AngularJS執行上下文。記住,大部分情況下(如在控制器,服務中),$apply都已經被執行過了。只有當你使用自定義的事件回調或者是使用第三方類庫的回調時,才需要自己執行$apply。

下面通過一個例子來講解如何實現“將用戶輸入綁定到視圖上”的效果。

<!doctype html>
<html ng-app>
  <head>
    <script src="http://code.angularjs.org/angular-1.1.0.min.js"></script>
  </head>
  <body>
    <input ng-model="name">
    <p>Hello {{name}}!</p>
  </body>
</html>

在編譯階段:
  input元素上的ng-model指令會給<input>輸入框綁定keydown事件;
  {{name}}這個變量替換表達式建立了一個 $watch ,來接受 name 變量改變的通知。
在執行期階段:
  按下任何一個鍵(以X鍵為例),都會觸發一個 input 輸入框的keydown事件;
  input 上的指令捕捉到 input 內容的改變,然後調用 $apply("name = 'X';")來更新處於AngularJS執行上下文中的模型;
  AngularJS將 name='X'應用到模型上;
  $digest 循環開始;這個循環是由兩個小循環組成的,這兩個小循環用來處理$evalAsync隊列和$watch列表。這個$digest循環直到模型“穩定”前會一直迭代。這個穩定具體指的是$evalAsync列表為空,並且$watch列表中檢測不到任何改變了。這個$evalAsync隊列是用來管理那些“視圖渲染前需要在當前棧外執行的操作”。這通常使用 setTimeout(0)來完成的。並且,因為浏覽器會根據事件隊列按順序渲染視圖,這時還會造成視圖的抖動。$watch列表是一個表達式的集合,這些表達式可能是自上次迭代後發生了改變的。如果檢測到了有改變,那麼$watch函數就會被調用,它通常會把新的值更新到DOM中。

  $watch 列表檢測到了name值的變化,然後通知 {{name}}變量替換的表達式,這個表達式負責將DOM進行更新;
  AngularJS退出執行上下文,然後退出Javascript上下文中的keydown事件;
  浏覽器以更新的文本重新渲染視圖。

作用域(Scope)

作用域是用來檢測模型的改變和為表達式提供執行上下文的。它是分層組織起來的,並且層級關系是緊跟著DOM的結構的。

下面這個例子演示了{{name}}表達式在不同的作用域下被解析成了不同的值

 

<!doctype html>
<html ng-app>
  <head>
    <script src="http://code.angularjs.org/angular-1.1.0.min.js"></script>
    <script>
        function GreetCtrl($scope) {
        $scope.name = 'World';
     }

     function ListCtrl($scope) {
        $scope.names = ['Igor', 'Misko', 'Vojta'];
     }
    </script>
  </head>
  <body>
    <div ng-controller="GreetCtrl">
      Hello {{name}}!
    </div>
    <div ng-controller="ListCtrl">
      <ol>
        <li ng-repeat="name in names">{{name}}</li>
      </ol>
    </div>
  </body>
</html>   

 

在GreetCtrl控制器中的name等於'World'。在ListCtrl控制器中的name等於'Igor', 'Misko', 'Vojta'。因為它們的作用域不一樣。

控制器

視圖背後的控制代碼就是控制器。它的主要工作內容是構造模型和回調方法,並把模型和回調方法一起發送到視圖。 視圖可以看做是作用域在模板(HTML)上的投影。而作用域是一個中間地帶,它把模型整理好傳遞給視圖,把浏覽器事件傳遞給控制器。控制器和視圖的分離非常重要,因為:

(1)控制器是由Javascript寫的。Javascript是命令式的,命令式的語言適合用來編寫應用的行為。控制器不應該包含任何關於渲染代碼(DOM引用或者片段)。
(2)視圖模板是用HTML寫的。HTML是聲明是的,聲明式的語言適合用來編寫UI。視圖不應該包含任何行為。
(3)因為控制器和視圖沒有直接的調用關系,所以可以使多個視圖對應同一個控制器。這對“換膚(re-skinning)”、適配不同設備(比如移動設備和台式機)、測試,都非常重要。

模型

模型就是用來和模板結合生成視圖的數據。模型在作用域中可以被引用,這樣才能被渲染生成視圖。和其他框架不一樣的是,Angularjs對模型本身沒有任何限制和要求。你不需要繼承任何類也不需要實現指定的方法。 模型可以是哈希形式的原生對象,也可以是完整對象類型。簡而言之,模型可以是原生的Javascript對象。

視圖

所謂視圖,就是指用戶所看見的。 視圖的生命周期由作為一個模板開始,它將和模型合並,並最終渲染到浏覽器的DOM中。與其他模板系統不同的是,AngularJS使用一種獨特的形式來渲染視圖。

其他模板 - 大部分模板系統工作原理,都是一開始獲取一個帶有特殊標記的HTML形式字符串。通常情況下模板的特殊標記破壞了HTML的語法,以至於模板是不能用HTML編輯器編輯的。然後這個字符串會被送到模板引擎那裡解析,並和數據合並。合並的結果是一個可以被浏覽器解析的HTML字符串。這個字符串會被.innerHTML方法寫到DOM中。使用innerHTML會造成浏覽器的重新渲染。當模型改變時,這整個流程又要重復一遍。模板的生存周期就是DOM的更新周期。這裡我想強調是,這些模板的基礎是字符串。
AngularJS - AngularJS和其它模板系統不同。它使用的是DOM而不是字符串。模板仍然是用HTML字符串寫的,並且它仍然是HTML。浏覽器將它解析成DOM, 然後這個DOM會作為輸入傳遞給模板引擎,也就是我們的編譯器。編譯器查看其中的指令,找到的指令後,會開始監視指令內容中相應的模型。 這樣做,就使得視圖能“連續地”更新,不需要模板和數據的重新合並。你的模型也就成了你視圖變化的唯一原因。

指令

一個指令 就是一種“由某個屬性、元素名稱、css類名出現而導致的行為,或者說是DOM的變化”。指令能讓你以一種聲明式的方法來擴展HTML表示能力。

Filters過濾器

過濾器扮演著數據翻譯的角色。一般他們主要用在數據需要格式化為本地格式的時候。它參照了UNIX過濾的規則,並且也實現了“|”(管道)語法。

模塊和注入器

每個AngularJS應用都有一個唯一的注入器。注入器提供一個通過名字查找對象實例的方法。它將所有對象緩存在內部,所以如果重復調用同一名稱的對象,每次調用都會得到同一個實例。如果調用的對象不存在,那麼注入器就會讓實例的工廠(instance factory)函數創建一個新的實例。

一個模塊就是一種配置注入器的實例的工廠函數的方式,我們也稱它為“提供者(provider)”。

var myModule = angular.module('myModule', [])

myModule.factory('serviceA', function() {      //定義serviceA的工廠函數,myModule模塊就是提供serviceA實例的工廠函數的提供者
   return {

  ......
  };
});

// 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');      //從注入器查找serviceA對象,這時注入器會讓實例serviceA的工廠函數factory創建一個新的實例serviceA返回

// always true because of instance cache
$injector.get('serviceA') === $injector.get('serviceA');

注入器真正強大之處在於讓方法和類型能夠通過注入器,請求到他們依賴的組件,而不需要自己加載依賴。

我們看看下面動態時間的這個例子:

 

<!doctype html>
<html ng-app="timeExampleModule">
  <head>
    <script src="http://code.angularjs.org/angular-1.1.0.min.js"></script>
    <script">
      angular.module('timeExampleModule', []).
        factory('time', function($timeout) {
           var time = {};
          (function tick() {
            time.now = new Date().toString();
            $timeout(tick, 1000);
          })();
          return time;
       });
    function ClockCtrl($scope, time) {
       $scope.time = time;
    }
    </script>
  </head>
  <body>
    <div ng-controller="ClockCtrl">
      Current time is: {{ time.now }}
    </div>
  </body>
</html>   

你只要把需要的依賴寫在函數參數裡。當AngularJS調用這個函數時,它會自動填充好需要的參數。這個例子中,當ng-controller實例化構造器ClockCtrl的時候,它自動提供了指明的依賴time實例對象。

AngularJS 命名空間

為了防止意外的命名沖突, AngularJS為可能沖突的對象名加以前綴"$"。所以請不要在你自己的代碼裡用"$"做前綴,以免和AngularJS代碼發生沖突。

AngularJS權威教程 清晰PDF版  http://www.linuxidc.com/Linux/2015-01/111429.htm

希望你喜歡,並分享我的工作~帶你走近AngularJS系列

  1. 帶你走近AngularJS - 基本功能介紹 http://www.linuxidc.com/Linux/2014-05/102140.htm
  2. 帶你走近AngularJS - 體驗指令實例 http://www.linuxidc.com/Linux/2014-05/102141.htm
  3. 帶你走近AngularJS - 創建自定義指令 http://www.linuxidc.com/Linux/2014-05/102142.htm

如何在 AngularJS 中對控制器進行單元測試 http://www.linuxidc.com/Linux/2013-12/94166.htm

在 AngularJS 應用中通過 JSON 文件來設置狀態 http://www.linuxidc.com/Linux/2014-07/104083.htm

AngularJS 之 Factory vs Service vs Provider http://www.linuxidc.com/Linux/2014-05/101475.htm

AngularJS —— 使用 ngResource、RESTful APIs 和 Spring MVC 框架提交數據 http://www.linuxidc.com/Linux/2014-07/104402.htm

AngularJS 的詳細介紹:請點這裡
AngularJS 的下載地址:請點這裡

Copyright © Linux教程網 All Rights Reserved