一個(gè)例子 - 入門AngularJS

一. 為什么要使用AngularJS

Angular.js 是一個(gè)MVW(Model-View-Whatever,不管是MVC或者M(jìn)VVM,統(tǒng)歸MDV(model Drive View))JavaScript框架,個(gè)人更覺(jué)得像MVVM框架, 其是Google推出的專門用于SPA(single-page-application)應(yīng)用框架.

  • 思考: MVVM模式是Model-View-ViewMode(模型-視圖-視圖模型)模式的簡(jiǎn)稱,其最早出現(xiàn)在微軟的WPF和Silverlight框架中, 現(xiàn)在AngularJS也是這一模式的繼承者, 那么為什么這些框架都不遺余力的去實(shí)現(xiàn)這一模式, 這一模式有什么好處, 下面我們就從大家熟悉的silverlight開(kāi)始, 剖析MVVM模式的實(shí)現(xiàn), 以及為什么要使用AngularJS.

Silverlight中的MVVM(Model-ViewModel-View), 基于數(shù)據(jù)綁定的設(shè)計(jì)模式


  1. Model層: 一個(gè)簡(jiǎn)單學(xué)生實(shí)體模型
public class Student
{
    public string Name { get; set; }
    public int Age { get; set; }
    public DateTime Date { get; set; }
}
  1. ViewModel層: 通過(guò)繼承INotifyPropertyChanged實(shí)現(xiàn)數(shù)據(jù)更新自動(dòng)通知變化的數(shù)據(jù)綁定
public class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    protected void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
public class ViewModel : ViewModelBase
{
    public ViewModel()
    {
         Student = new Student();
         Student.Date = DateTime.Today.Date;
         Student.Name = "Jason";
         Student.Age = 18;
    }
    private Student _student;
    public Student Student
    {
        get
        {
            return _student;
        }
        set
        {
            _student = value;
            NotifyPropertyChanged("Student");
        }
    }
}
  1. View層(偽代碼): 通過(guò)Binding寫法綁定ViewModel中的數(shù)據(jù), 同時(shí)可以配置綁定方式
<TextBox Text="{Binding Student.Name, Mode=OneWay}"/>
<TextBox Text="{Binding Student.Age, Mode=TwoWay}"/>
<TextBox Text="{Binding Student.Date, Mode=OneTime}"/>
  1. 參考: A Simple Silverlight Application Implementing MVVM

AngularJs中的MVW(Model-View-Whatever),個(gè)人理解為MVVM


  1. 示例代碼
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<!----------------------引入AngularJs的包------------------------->
<script src="http://cdn.static.runoob.com/libs/angular.js/1.4.6/angular.min.js"></script>
<body ng-app="myApp" >
    <!------------------------View層------------------------------>
    <div ng-controller="myCtrl">
        姓名:  <input type="text" ng-model="student.name"><br>
        年齡:  <input type="text" ng-model="student.age"><br>
        入學(xué)時(shí)間:  <input type="text" ng-model="student.date"><br>
        
        <br>
        學(xué)生信息: {{student.name + " " + student.age +" " + student.date}}
    </div>
    <!------------------------View層------------------------------>
    
    <!-------ViewModel層($scope) / Controller層(controller)------->
    <script>
        var app = angular.module('myApp', []);
        app.controller('myCtrl', function ($scope) {
            //---------------Model層: student--------------//
            $scope.student = {
                name: "Jason",
                age: 17,
                date: "2015-04-01"
            };
            //---------------Model層: student--------------//
        });
    </script>
    <!-------ViewModel層($scope) / Controller層(controller)------->
</body>
</html>
  1. talk is cheap, show me the demo, try it yourself

  2. MVVM模式圖

    image
  • 使用AngularJS的原因:

    1. 數(shù)據(jù)綁定: 一個(gè)完整的基于數(shù)據(jù)綁定的MVVM模式的框架,優(yōu)勢(shì)如下

      1. 低耦合:View可以獨(dú)立于Model變化和修改,同一個(gè)ViewModel可以被多個(gè)View復(fù)用;并且可以做到View和Model的變化互不影響;
      2. 可重用性:可以把一些視圖的邏輯放在ViewModel,讓多個(gè)View復(fù)用;
      3. 獨(dú)立開(kāi)發(fā):開(kāi)發(fā)人員可以專注與業(yè)務(wù)邏輯和數(shù)據(jù)的開(kāi)發(fā)(ViewModel),界面設(shè)計(jì)人員可以專注于UI(View)的設(shè)計(jì);
      4. 可測(cè)試性:清晰的View分層,使得針對(duì)表現(xiàn)層業(yè)務(wù)邏輯的測(cè)試更容易,更簡(jiǎn)單。
    2. 可擴(kuò)展HTML: 使用AngularJS,你可以操作XML一樣操作HTML,創(chuàng)建自己的HTML標(biāo)簽和屬性的定義, 在angualrjs中用==指令==(directive)來(lái)實(shí)現(xiàn)這一切, 如上面的ng-app, ng-controller都是angularjs自帶的指令

    3. 依賴注入: 一種軟件設(shè)計(jì)模式,在這種模式下,一個(gè)或更多的依賴(或服務(wù))被注入(或者通過(guò)引用傳遞)到一個(gè)獨(dú)立的對(duì)象(或客戶端)中,然后成為了該客戶端狀態(tài)的一部分。在AngularJs中==服務(wù)==(Service)就通過(guò)依賴注入使用, 簡(jiǎn)單來(lái)說(shuō)就是: ==沒(méi)事你(服務(wù))不要來(lái)找我,有事我會(huì)去找你(服務(wù))。==

      // 定義一個(gè)模塊
      var app = angular.module("myApp", []);
      
      // 創(chuàng)建服務(wù) "AgeService" 
      app.service('AgeService', function() {
        // 用于判斷年齡是否是成年人
         this.judgeAdult = function(age) {
            if (age >= 18) {
                 return true;
            } else {
                 return false;
            }
         }
      }); 
      
      // 在控制器中依賴注入AgeService服務(wù)
      app.controller('myCtrl', function ($scope, AgeService) {
          //---------------Model層: student--------------//
          $scope.student = {
              name: "Jason",
              age: 17,
              date: "2015-04-01"
          };
          //---------------Model層: student--------------//
          
          // 使用AgeService服務(wù)里面的方法判斷是否成年
          $scope.isAdult = AgeService.judgeAdult($scope.student.age);
      });
      
      // 增加View層顯示
      是否成年:  <input type="text" ng-model="isAdult"><br>
      
      

二. 如何開(kāi)始學(xué)習(xí)AngularJS

  1. 從示例中了解AngularJS的基本概念
    1. 引用AngularJS包

      <script src="http://cdn.static.runoob.com/libs/angular.js/1.4.6/angular.min.js"></script>
      
    2. 啟動(dòng)AngularJS(ng-app):首先要告訴AngularJS我們的應(yīng)用運(yùn)行在DOM結(jié)構(gòu)的哪一部分,我們可以把==指令ng-app==設(shè)在任何DOM元素上,然后該元素就會(huì)成為AngularJS啟動(dòng)運(yùn)行我們應(yīng)用的地方, 示例中 <body ng-app="myApp"></body> 告訴AngularJS擁有<body>下面的DOM區(qū)域并且從這里開(kāi)始啟動(dòng), 注意有且只能有一個(gè)地方標(biāo)注ng-app.

      <body ng-app="myApp">
          // ... ...
      </body>
      
    3. 創(chuàng)建模塊(Module): 注意到在上面ng-app="myApp"中myApp, 其實(shí)在AngularJS啟動(dòng)的時(shí)候有個(gè)啟動(dòng)器, 如果ng-app不帶屬性值,啟動(dòng)器就會(huì)自動(dòng)初始化(默認(rèn)配置)應(yīng)用程序, 但是有屬性值, 比如我們的myApp, 這代表告訴AngularJS要加載叫做myApp的模塊作為初始化程序,所謂AngularJS模塊,其實(shí)就是==一系列函數(shù)的集合==,當(dāng)應(yīng)用被啟動(dòng)時(shí),這些函數(shù)就會(huì)被執(zhí)行, 示例中創(chuàng)建了叫做“myApp”的AngularJS模塊, 注意里面有個(gè)空的數(shù)組,這個(gè)數(shù)組是myApp模塊依賴的模塊的列表,為空代表會(huì)創(chuàng)建一個(gè)模塊.

      // 創(chuàng)建myApp區(qū)域的模塊
      var app = angular.module("myApp", []);
      
    4. 控制器(Controller): 控制 AngularJS模塊的數(shù)據(jù), 示例中為myApp模塊增加了一個(gè)叫做myCtrl的控制器, 通過(guò)ng-controller="myCtrl" 在DOM中創(chuàng)建控制器并劃定了控制的范圍, ==同時(shí)創(chuàng)建了這個(gè)范圍的作用域scope對(duì)象==, 在js控制器中可以傳入并且訪問(wèn)scope對(duì)象, 例子中在$scope中創(chuàng)建了student對(duì)象, 我們就可以在ng-controller="myCtrl"屬性的DOM元素==任何子元素==里訪問(wèn)這個(gè)student對(duì)象,實(shí)現(xiàn)雙向綁定.

      // HTML
      <div ng-controller="myCtrl">
         //... ...
      </div>
      
      // JS
      app.controller('myCtrl', function ($scope) {
          $scope.student = {
              name: "Jason",
              age: 17,
              date: "2015-04-01"
          };
      });
      
    5. **作用域(scope)**: 是一個(gè)對(duì)象,有可用的方法和屬性, 是應(yīng)用在 HTML (視圖) 和 JavaScript (控制器)之間的紐帶, 示例中,在myCtrl的控制器中傳入了scope對(duì)象, 在$scope中添加任何方法和屬性, 在HTML(視圖)指定的控制器下的DOM元素都可以訪問(wèn)這些屬性方法.

      1. 作用域范圍: 所有的應(yīng)用都有一個(gè) rootScope,它可以作用在 ng-app 指令包含的所有 HTML 元素中。rootScope 可作用于整個(gè)應(yīng)用中。是各個(gè) controller 中 scope 的橋梁。用 rootscope 定義的值,可以在各個(gè) controller 中使用。
        <body ng-app="myApp">
            <div ng-controller="ParentController">
                <div ng-controller="ChildController">
                </div>
            </div>
        </body>
        
    6. 指令(Directive)和表達(dá)式: 上面的示例中不斷出現(xiàn)各種原生HTML中沒(méi)有的各種屬性, 其實(shí)他們?cè)贏ngularJS中叫做指令, AngularJS為我們創(chuàng)建了很多指令, ==指令實(shí)際上就是綁定在DOM元素上的函數(shù)==, 可以調(diào)用方法(ng-click), 定義行為(ng-app), 綁定控制器(ng-controller), 綁定數(shù)據(jù)(ng-model)等等.

      ng-app: 指令定義了AngularJS應(yīng)用程序的根元素
      ng-model: 指令綁定HTML元素到應(yīng)用程序數(shù)據(jù)。
      ng-controller: 指令定義了應(yīng)用程序控制器。
      ... ...
      
      {{student.name}} : 表達(dá)式與 ng-model="student.name" 相同, 實(shí)現(xiàn)數(shù)據(jù)綁定
      
      1. 指令執(zhí)行: 當(dāng)一個(gè)AngularJS應(yīng)用啟動(dòng),Angular編譯器就會(huì)遍歷DOM樹(shù)(從有ng-app指令屬性的那個(gè)DOM元素開(kāi)始),解析HTML,尋找這些指令函數(shù)。當(dāng)在一個(gè)DOM元素上找到一個(gè)或多個(gè)這樣的指令函數(shù),它們就會(huì)被收集起來(lái)、排序,然后按照優(yōu)先級(jí)順序被執(zhí)行
    7. 服務(wù)(Service): Services都是單例的,就是說(shuō)在一個(gè)應(yīng)用中,每一個(gè)Service對(duì)象只會(huì)被實(shí)例化一次(用$injector服務(wù)),主要負(fù)責(zé)==提供一個(gè)接口把特定函數(shù)需要的方法放在一起==, 就拿上面講依賴注入的AgeService服務(wù)舉例子, 這個(gè)服務(wù)就提供了判斷是否成年的函數(shù)方法, 在需要的時(shí)候注入就可以直接使用, 非常方便. 同樣, AngularJS內(nèi)建了很多服務(wù), 實(shí)現(xiàn)了很多功能, 以后在開(kāi)發(fā)的時(shí)候直接注入進(jìn)來(lái)就可以用了

      app.service('AgeService', function() {
        // 用于判斷年齡是否是成年人
         this.judgeAdult = function(age) {
            if (age >= 18) {
                 return true;
            } else {
                 return false;
            }
         }
      }); 
      
  2. 詳細(xì)的AngularJS使用教程: AngularJS教程 | 菜鳥(niǎo)教程
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容