一. 为什么要使用AngularJS
Angular.js 是一个MVW(Model-View-Whatever,不管是MVC或者MVVM,统归MDV(model Drive View))JavaScript框架,个人更觉得像MVVM框架, 其是Google推出的专门用于SPA(single-page-application)应用框架.
- 思考: MVVM模式是Model-View-ViewMode(模型-视图-视图模型)模式的简称,其最早出现在微软的WPF和Silverlight框架中, 现在AngularJS也是这一模式的继承者, 那么为什么这些框架都不遗余力的去实现这一模式, 这一模式有什么好处, 下面我们就从大家熟悉的silverlight开始, 剖析MVVM模式的实现, 以及为什么要使用AngularJS.
Silverlight中的MVVM(Model-ViewModel-View), 基于数据绑定的设计模式
- Model层: 一个简单学生实体模型
public class Student
{
public string Name { get; set; }
public int Age { get; set; }
public DateTime Date { get; set; }
}
- ViewModel层: 通过继承INotifyPropertyChanged实现数据更新自动通知变化的数据绑定
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");
}
}
}
- View层(伪代码): 通过Binding写法绑定ViewModel中的数据, 同时可以配置绑定方式
<TextBox Text="{Binding Student.Name, Mode=OneWay}"/>
<TextBox Text="{Binding Student.Age, Mode=TwoWay}"/>
<TextBox Text="{Binding Student.Date, Mode=OneTime}"/>
AngularJs中的MVW(Model-View-Whatever),个人理解为MVVM
- 示例代码
<!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>
入学时间: <input type="text" ng-model="student.date"><br>
<br>
学生信息: {{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>
-
使用AngularJS的原因:
-
数据绑定: 一个完整的基于数据绑定的MVVM模式的框架,优势如下
- 低耦合:View可以独立于Model变化和修改,同一个ViewModel可以被多个View复用;并且可以做到View和Model的变化互不影响;
- 可重用性:可以把一些视图的逻辑放在ViewModel,让多个View复用;
- 独立开发:开发人员可以专注与业务逻辑和数据的开发(ViewModel),界面设计人员可以专注于UI(View)的设计;
- 可测试性:清晰的View分层,使得针对表现层业务逻辑的测试更容易,更简单。
可扩展HTML: 使用AngularJS,你可以操作XML一样操作HTML,创建自己的HTML标签和属性的定义, 在angualrjs中用==指令==(directive)来实现这一切, 如上面的ng-app, ng-controller都是angularjs自带的指令
-
依赖注入: 一种软件设计模式,在这种模式下,一个或更多的依赖(或服务)被注入(或者通过引用传递)到一个独立的对象(或客户端)中,然后成为了该客户端状态的一部分。在AngularJs中==服务==(Service)就通过依赖注入使用, 简单来说就是: ==没事你(服务)不要来找我,有事我会去找你(服务)。==
// 定义一个模块 var app = angular.module("myApp", []); // 创建服务 "AgeService" app.service('AgeService', function() { // 用于判断年龄是否是成年人 this.judgeAdult = function(age) { if (age >= 18) { return true; } else { return false; } } }); // 在控制器中依赖注入AgeService服务 app.controller('myCtrl', function ($scope, AgeService) { //---------------Model层: student--------------// $scope.student = { name: "Jason", age: 17, date: "2015-04-01" }; //---------------Model层: student--------------// // 使用AgeService服务里面的方法判断是否成年 $scope.isAdult = AgeService.judgeAdult($scope.student.age); }); // 增加View层显示 是否成年: <input type="text" ng-model="isAdult"><br>
-
二. 如何开始学习AngularJS
- 从示例中了解AngularJS的基本概念
-
引用AngularJS包
<script src="http://cdn.static.runoob.com/libs/angular.js/1.4.6/angular.min.js"></script>
-
启动AngularJS(ng-app):首先要告诉AngularJS我们的应用运行在DOM结构的哪一部分,我们可以把==指令ng-app==设在任何DOM元素上,然后该元素就会成为AngularJS启动运行我们应用的地方, 示例中
<body ng-app="myApp"></body>
告诉AngularJS拥有<body>
下面的DOM区域并且从这里开始启动, 注意有且只能有一个地方标注ng-app.<body ng-app="myApp"> // ... ... </body>
-
创建模块(Module): 注意到在上面
ng-app="myApp"
中myApp, 其实在AngularJS启动的时候有个启动器, 如果ng-app不带属性值,启动器就会自动初始化(默认配置)应用程序, 但是有属性值, 比如我们的myApp, 这代表告诉AngularJS要加载叫做myApp的模块作为初始化程序,所谓AngularJS模块,其实就是==一系列函数的集合==,当应用被启动时,这些函数就会被执行, 示例中创建了叫做“myApp”的AngularJS模块, 注意里面有个空的数组,这个数组是myApp模块依赖的模块的列表,为空代表会创建一个模块.// 创建myApp区域的模块 var app = angular.module("myApp", []);
-
控制器(Controller): 控制 AngularJS模块的数据, 示例中为myApp模块增加了一个叫做myCtrl的控制器, 通过ng-controller="myCtrl" 在DOM中创建控制器并划定了控制的范围, ==同时创建了这个范围的作用域scope对象, 例子中在$scope中创建了student对象, 我们就可以在ng-controller="myCtrl"属性的DOM元素==任何子元素==里访问这个student对象,实现双向绑定.
// HTML <div ng-controller="myCtrl"> //... ... </div> // JS app.controller('myCtrl', function ($scope) { $scope.student = { name: "Jason", age: 17, date: "2015-04-01" }; });
-
**作用域(scope对象, 在$scope中添加任何方法和属性, 在HTML(视图)指定的控制器下的DOM元素都可以访问这些属性方法.
-
作用域范围: 所有的应用都有一个 rootScope 可作用于整个应用中。是各个 controller 中 scope 的桥梁。用 rootscope 定义的值,可以在各个 controller 中使用。
<body ng-app="myApp"> <div ng-controller="ParentController"> <div ng-controller="ChildController"> </div> </div> </body>
-
作用域范围: 所有的应用都有一个 rootScope 可作用于整个应用中。是各个 controller 中 scope 的桥梁。用 rootscope 定义的值,可以在各个 controller 中使用。
-
指令(Directive)和表达式: 上面的示例中不断出现各种原生HTML中没有的各种属性, 其实他们在AngularJS中叫做指令, AngularJS为我们创建了很多指令, ==指令实际上就是绑定在DOM元素上的函数==, 可以调用方法(ng-click), 定义行为(ng-app), 绑定控制器(ng-controller), 绑定数据(ng-model)等等.
ng-app: 指令定义了AngularJS应用程序的根元素 ng-model: 指令绑定HTML元素到应用程序数据。 ng-controller: 指令定义了应用程序控制器。 ... ... {{student.name}} : 表达式与 ng-model="student.name" 相同, 实现数据绑定
- 指令执行: 当一个AngularJS应用启动,Angular编译器就会遍历DOM树(从有ng-app指令属性的那个DOM元素开始),解析HTML,寻找这些指令函数。当在一个DOM元素上找到一个或多个这样的指令函数,它们就会被收集起来、排序,然后按照优先级顺序被执行
-
服务(Service): Services都是单例的,就是说在一个应用中,每一个Service对象只会被实例化一次(用$injector服务),主要负责==提供一个接口把特定函数需要的方法放在一起==, 就拿上面讲依赖注入的AgeService服务举例子, 这个服务就提供了判断是否成年的函数方法, 在需要的时候注入就可以直接使用, 非常方便. 同样, AngularJS内建了很多服务, 实现了很多功能, 以后在开发的时候直接注入进来就可以用了
app.service('AgeService', function() { // 用于判断年龄是否是成年人 this.judgeAdult = function(age) { if (age >= 18) { return true; } else { return false; } } });
-
- 详细的AngularJS使用教程: AngularJS教程 | 菜鸟教程