AngularJS学习笔记(1)

书籍信息

精通AngularJS

工具

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) {

        },

        //其他方法
    }
})
  1. provider是一个函数,返回包含$get属性的对象,该属性是一个工厂函数,被调用时返回service的实例。provider就是$get属性为工厂方法的对象??怎么理解
  2. provider函数返回的对象可以有其他方法和属性,在$get方法被调用前可以配置信息。
模块的生命周期

为了支持provider,angularJS将模块的生命周期分为两个阶段:

  1. 配置阶段
    Provider的配置代码如下
myMod.config(function(notificationsServiceProvider){
	notificationsServiceProvider.setMaxLen(5);
})
  1. 运行阶段
    例如,记录应用的开始时间
angular.module('upTimeApp', []).run(function($rootScope){
	$rootScope.appStarted = new Date();
});

在模板中访问

Application started at: {{appStarted}}
  1. 不同阶段的注册方法
    | | 对象种类 | 是否可以在配置阶段注入 | 是否可以在运行阶段注入|
    |:--------|:----------------------|:------------------😐:--------😐
    | 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模块中创建服务,并使用依赖注入将这些服务穿起来。
posted @ 2016-03-14 16:45  Gibbon  阅读(162)  评论(0编辑  收藏  举报