AngularJS学习笔记(1)
书籍信息
工具
Sublime Text:
http://github.com/angular-ui/AngularJS-sublime-package
Chrome:
Batarang
Hello World!
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.js"></script>
</head>
<body ng-app ng-init="name='world'">
<h1>Hello, {{name}}!</h1>
</body>
</html>
Angular控制器
规则:永远不要在AngularJS的控制器中操纵DOM元素。
模块与依赖注入
angular.module('hello',[]).controller('HelloCtrl', function($scope){
$scope.name = 'World'
});
全局命名空间 angular
规则:永远不要在复杂的真实应用中使用全局定义的控制器。
使用ng-app
属性指定模块的名字。
接入依赖注入机制的第一步是将对象注册到模块上。AngularJS的$provide服务可以注册不同的对象创建方案。之后$injector服务会解释这些方案,生成完备的可用的对象实例。$injector服务创建的对象成为服务(service)。
value 值
让AngularJS管理对象,注册已初始化好的对象
var myMod = angular.module('myMod', []);
myMode.value('notificationsArchive', new NotifacationsArchieve());
通过value注册的对象不能依赖于其他对象,只对非常简单的对象有效,例如内建对象和对象字面量。
service 服务
NotificationService依赖于notifactionArchive,所以不能注册为值对象,要使用service方法注册构造函数。
myMod.service('notificationsService', NotificatinsSerivce);
var NotificationsService = function (notificationsArchive) {
this.nofificationsArchive = notificationsArchive;
}
通过service,AngularJS能够管理那些构造函数创建的对象了。
factory 工厂
任何能够创建对象的函数都可以注册,相比service更加灵活(?灵活在什么地方?)
factory方法返回的对象可以是任何有效的js对象,也可以是function对象。facotry返回的函数是闭包。
代码示例:
myMod.factory('notificationsService', function(notificationsArchive){
var MAX_LEN = 10;
var notifications = []'
return {
push: function(notification) {
var notificationToArchive;
var newLen = notifications.unshift(notification);
//
if (newLen > MAX_LEN) {
notificationToArchive = this.notifications.pop();
notificationsArchive.archive(notificationToArchive);
}
},
// NotificationsService的其他方法
}
})
constant 常量
常量可以注册在模块的级别上,可以被注入。
myMode.factory('notificationsService', function(notificationsArchive, MAX_LEN){
...
// 创建逻辑
})
在NotificationsService之外,配置信息注册在模块上,
myMod.constant('MAX_LEN', 10);
- 用途:不同的应用使用共同的服务
- 缺点:当声明常量依赖时,必须提供那个常量的值。
provider 提供者
示例代码
myMod.provider('notificationsService', function(){
var config = {
maxLen: 10;
};
var notifications = [];
return {
setMaxLen: function(maxLen) {
},
$get: function(notificationsArchive) {
},
//其他方法
}
})
- provider是一个函数,返回包含$get属性的对象,该属性是一个工厂函数,被调用时返回service的实例。provider就是$get属性为工厂方法的对象??怎么理解
- provider函数返回的对象可以有其他方法和属性,在$get方法被调用前可以配置信息。
模块的生命周期
为了支持provider,angularJS将模块的生命周期分为两个阶段:
- 配置阶段
Provider的配置代码如下
myMod.config(function(notificationsServiceProvider){
notificationsServiceProvider.setMaxLen(5);
})
- 运行阶段
例如,记录应用的开始时间
angular.module('upTimeApp', []).run(function($rootScope){
$rootScope.appStarted = new Date();
});
在模板中访问
Application started at: {{appStarted}}
- 不同阶段的注册方法
| | 对象种类 | 是否可以在配置阶段注入 | 是否可以在运行阶段注入|
|:--------|:----------------------|:------------------😐:--------😐
| Constant | 常量值 | Yes | Yes |
| Variable | 变量值 | - | Yes |
| Service | 构造函数创建的新对象 | - | Yes |
| Facotry | 工厂函数返回的新对象 | - | Yes |
| Provider | $get工厂函数创建的新对象 | Yes | - |
模块依赖
处理AngularJS模块时,我们要考虑模块层次和服务层次。
问题:
- 在某个AngularJS模块定义的服务可以依赖于另一个模块的服务吗?
- 在子模块定义的服务可以依赖于在父模块定义的服务吗?还是只能依赖在子模块定义的服务?
- 是否有只在某个特定模块里可见的模块私有服务?
- 在不同的模块里是否可以有同名的服务?
答案:子模块定义的服务可以依赖于在父模块定义的服务
模块 - app
依赖模块engines,
定义服务car,依赖服务dieselEngine
模块 - engines
定义服务dieselEngine
即,在app.car中可以注入engines.diselEngine,app和engines是父子关系。
在兄弟模块定义的服务相互之间也是可见的。
模块 - app
依赖模块engines, cars
模块 - cars
定义服务car,依赖服务dieselEngine
模块 - engines
定义服务dieselEngine
即,在cars.car中可以注入engines.diselEngine,cars和engines是兄弟关系。
在一个应用的模块中定义的服务对所有其他模块都是可见的。模块的层次不会影响服务对其他模块的可见性。一个应用的AngularJS启动时,在各个模块定义的服务都会合并到一个应用中,即全局命名空间。
所以服务的名字是唯一的。这样我们可以依赖于一个模块,同时覆盖整个模块的某些服务。
示例
angular.module('app', ['engines', 'cars'])
.controller('AppCtrl', function ($scope, car) {
car.start();
});
angular.module('cars', [])
.factory('car', function ($log, dieselEngine) {
return {
start: function() {
$log.info('Starting ' + dieselEngine.type);
}
};
})
.factory('dieselEngine', function () {
return {
type: 'custom diesel'
};
});
angular.module('engines', [])
.factory('dieselEngine', function () {
return {
type: 'diesel'
};
});
输出:Starting custom diesel
解释:服务car和dieselEngine服务一起注入,来自模块cars的服务dieselEngine覆盖了模块engines的服务dieselEngine。
疑问:为什么使用AngularJS的模块?
既然服务都集合在一个命名空间下,为什么还要费力地将服务分割到不同的模块?AngularJS模块可以帮助我们在一个应用中组织多个JS文件,小而集中的模块有利于单元测试。
Angular与*
MVC框架比较
TodoMVC 一个帮助选择MVC框架的工程
https://github.com/tastejs/todomvc
http://todomvc.com/
AngularJS的优点
- 自动刷新和双向绑定
- 模板语言使用基于HTML的LiveDOM
- 声明式UI
- UI模板机制并不限制JS代码
可测试性
- 依赖注入引擎有利于测试
- AngularJS文档的所有示例代码都有测试代码
- 测试工具:Testacular
jQuery与AngularJS
AngularJS内嵌了jqLite,jqLite是jQuery的子集,集中于DOM操作。如果先于AngularJS引用jQuery,AngularJS将使用这个jQuery操作DOM。
AngularJS是以模型为中心,jQuery是以DOM为中心
总结
- 使用AngularJS的控制器、范围和视图
- 在AngularJS模块中创建服务,并使用依赖注入将这些服务穿起来。