介绍
AngularJS是一款由Google公司开发维护的前端MVC框架,其克服了HTML在构建应用上的诸多不足,从而降低了开发成本提升了开发效率。
特点
- AngularJS有着诸多特性,比如模块化、双向数据绑定、语义化标签、依赖注入等。它与我们之前学习的jQuery是有一定的区别的,jQuery更准确来说只一个类库(类库指的是一系列函数的集合)以DOM做为驱动(核心),而AngularJS则一个框架(诸多类库的集合)以数据做为驱动(核心)。
- 框架对开发的流程和模式做了约束,开发者遵照约束进行开发,更注重实际业务逻辑,与之类似的框架还有BackBone、KnockoutJS、Vue、React等。
下载
1.通过AngularJS官方下载
2.通过npm下载,npm install angular
3.通过bower下载,bower install angular体验
1
2
3
4
5
6
7
8
9
10
11
12
13<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>AngularJS 入门指南</title>
</head>
<body ng-app>
<input type="text" ng-model="name">
<span>hello {{name}}</span>
<!-- 引入AngularJS框架 -->
<script src="./libs/angular.min.js"></script>
</body>
</html>
MVC
MVC是一种开发模式,由模型(Model)、视图(View)、控制器(Controller)3部分构成,采用这种开发模式为合理组织代码提供了方便、降低了代码间的耦合度、功能结构清晰可见。
- 模型(Model)一般用来处理数据(读取/设置),比如数据库操作
- 视图(View)一般用来展示数据,比如通过HTML展示
- 控制器(Controller)一般用做连接模型和视图的桥梁
MVC更多应用在后端开发程序里,后被引入到前端开发中,由于受到前端技术的限制便有了一些细节的调整,进而出现了很多MVC的衍生版(子集)如MVVM、MVW、MVP、MV*等。
模块化
- 通过AngularJS构建应用(App)时是以模块化(Module)的方式组织的,即将整个应用划分成若干模块,每个模块都有各自的职责,最终组合成一个整体。
基本结构
应用(APP)
- 通过为任一HTML标签添加ng-app属性,可以指定一个应用(App),此标签所包裹的内容都属于应用(App)的一部分。
1 | <!DOCTYPE html> |
或者
1 | <!DOCTYPE html> |
模块(module)
- AngularJS提供了一个全局对象angular,在此全局对象下存在若干个方法,其中angular.module方法用来定义一个模块(Module)。
1 | // 第1个参数代表模块名称 |
注:应用(App)其本质也是一个模块
控制器(controller)
- 控制器(Controller)作为连接模型(Model)和视图(View)的桥梁存在,通过模块实例对象方法controller来定义。
1 | // App是上述的应用实例 |
- 通过控制器(Controller)将模型(Model)数据展示到对应的视图(View)上,每个视图(View)都可以对应1个或多个控制器(Controller),通过为HTML标签添加ng-controller属性并赋值相应的控制器(Controller)的名称,就确立了关联关系。
1 | <!-- ng-controller值为控制器的名称 --> |
完整实例1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19<!DOCTYPE html>
<html lang="en" ng-app="App">
<head>
<meta charset="UTF-8">
<title>AngularJS 入门指南</title>
</head>
<body>
<div class="box" ng-controller="DemoController">
{{ somedata }}
</div>
<script src="./libs/angular.min.js"></script>
<script>
var App = angular.module('App', []);
App.controller('DemoController', ['$scope', function($scope) {
$scope.somedata = 'Study AngularJS by myself!';
}])
</script>
</body>
</html>
指令
HTML在构建应用(App)时存在诸多不足之处,AngularJS通过扩展一系列的HTML属性或标签来弥补这些缺陷,所谓指令就是AngularJS自定义的HTML属性或标签,AngularJS自身负责解析这些自定义的属性或标签,AngularJS指令都是以ng-做为前缀的,例如ng-app、ng-controller、ng-repeat等。
1.内置指令
1 | 1.作用域类 |
2.服务
1.内置服务$http1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43angular.module('s1.app',[])
//angular里面的内置服务
.run(function($http, $rootScope){
// $http.get('data.js')
// .success(function(data){
// console.log(data);
// })
// .error(function(data){
// console.log("error"+data);
// })
//服务的标准用法
$http({
url:'data.js',
data:{},
method:'get'
})
.success(function(data){
console.log(data);
})
.error(function(data){
console.log("error"+data);
})
//或者这样使用
var promise = $http({
url:'data.js',
method:'jsonp',//GET/DELETE/HEAD/JSONP/POST/PUT
data:{},//your data
headers:{
"Content-Type":''//your config
}
});
promise.then(function(resp){
// resp是一个响应的对象
console.log(resp);
},function(resp){
//带有错误信息
console.log(resp);
})
})
2.自定义服务service
service通过构造函数的方式创建service,并返回一个实例化的对象。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15var app = angular.module('s1.app', []);
// 第一个参数:服务的名字
// 第二个参数:服务的构造器
// 使用:在依赖注入时,输入服务的名字,就能拿到“服务对象”。
// 服务对象其实是通过构造函数的方式创建的service
app.service('DemoService', function () {
this.msg = 'hello demo service';
});
app.run(function (DemoService, $rootScope) {
$rootScope.data = {
msg: DemoService.msg
}
})
3.自定义服务factory
factory把service的方法和数据放在一个对象里面,并返回。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17var app = angular.module('s1.app', []);
// 第一个参数:服务的名字
// 第二个参数:服务的工厂函数
app.factory('DemoService',function () {
// 服务的工厂函数的返回值,才是服务对象
return {
msg:'this is from factory'
}
});
app.run(function (DemoService, $rootScope) {
$rootScope.data = {
msg: DemoService.msg
}
})
4.自定义服务provider
provider创建一个可通过config配置的service,$get中返回的就是用factory创建service的内容。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 angular.module('s1.app', [])
.provider('DataService', function () {
var host = 'http://localhost:3000';
// 配置对象
return {
setHost: function (newHostUrl) {
host = newHostUrl
},
$get: function () {
// 服务对象
return {
getIndexUrl: function () {
return host + '/index.html'
},
// setHost :function (newHostUrl) {
// host = newHostUrl
// }
}
}
}
})
.config(function (DataService) {
DataService.setHost('http://www.baidu.com')
})
.run(function ($rootScope, DataService) {
// DataService.setHost('http://www.baidu.com');
// // 把设置函数放到服务对象里的方法,没办法使用
// 1这种设置也行,但是不是优化处理,我们想要在使用run函数之前的时候,就能获取到设置的值,而不是调用run的时候再获取,因此要使用config,在真正的程序运行之前,数据就设置好
$rootScope.url = DataService.getIndexUrl();
})
3.过滤器
1.内置过滤器
1 | {{ expression | filter }} |
1 | <ul ng-controller="DemoController"> |
- 使用ng提供的内置$filter服务(需要引入进来)
1 | $scope.num = $filter('currency')(12345);//第一个参数过滤器名字,第二个参数是过滤值 |
- 自定义过滤器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23<div ng-controller="DemoController">
{{content|capitalize}}
</div>
<script src="libs/angular.min.js"></script>
<script>
var App = angular.module('App', []);
App.controller('DemoController', ['$scope', function($scope) {
$scope.content = 'my name is itcast';
}]);
// 定义自定义过滤器
//参数1:过滤器名字
//参数2:过滤器执行的程序
App.filter('capitalize', function () {
// 下面是固定格式
return function (input) {
console.log(input);//my name is itcast
return input[0].toUpperCase() + input.slice(1);//My name is itcast
}
});
</script>
4.自定义指令
1 | / 定义模块 |
使用:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>AngularJS 入门指南</title>
</head>
<body ng-app="App">
<!-- 使用自定义指令 -->
<div my-directive></div>
<script src="./libs/angular.min.js"></script>
<script>
// 定义模块
var App = angular.module('App', []);
// 自定义指令
// 第1个参数代表指令名称
// 第2个参数配置指令参数
App.directive('myDirective', function () {
return {
// 自定义指令的类型
restrict: 'EAC',
// 自定义指令模板
template: '<h1>Hello AngularJS!</h1>',
// 是否替换原始标签
replace: true
// .... 还有其它参数
}
});
</script>
</body>
</html>
1 | // 使用自定义指令的嵌入,加上变量,双向绑定 |
1 | 使用双向绑定 = |
1 | //在隔离作用域访问指令外部的作用域的方法还有一种,就是&。 |
5. ng-transclude
如果页面中书写了这个指令说明是可以嵌入内部元素的
6. $compile
编译一段HTML字符串或者DOM的模板,产生一个将scope和模板连接到一起的函数。
$compile(element,transclude,maxPriority);
element:将要被编译和插入模板的元素或者HTML字符串。
transclude:指令内有效的函数。Function(angular.Scope,cloneAttachFn=)
maxPriority:只有在指令比给定的优先级低时应用。只影响根元素,不影响子元素。
返回:
一个用于绑定HTML模板到一个作用域的连接函数。
7. angular中的http拦截器Interceptors的实现
在angularJs中增加了一个全局的http请求统一做出处理的api–interceptors
Interceptors有两个处理时机, 分别是:
(1) 其它程序代码执行HTTP请求之后,在实际从浏览器发出请求之前,即处理请求
(2) 得到请求的响应之后,在交给其它程序代码处理之前,即处理请求的响应
其引用场景包括:
(1) 全局处理错误
(2) 统一进行身份验证一类的处理
(3) 对所有发出去的请求进行预处理
(4) 对所有收到的响应进行预处理等等
数据绑定
- AngularJS是以数据做为驱动的MVC框架,所有模型(Model)里的数据经过控制器(Controller)展示到视图(View)中。
- 所谓数据绑定指的就是将模型(Model)中的数据与相应的视图(View)进行关联,分别有单向绑定和双向绑定两种方式。
1.单项数据绑定
- 单向数据绑定是指将模型(Model)数据,按着写好的视图(View)模板生成HTML标签,然后追加到DOM中显示,如之前所学的artTemplate 模板引擎的工作方式。
如上图所示,只能模型(Model)数据向视图(View)传递。
2.双向数据绑定
- 双向绑定则可以实现模型(Model)数据和视图(View)模板的双向传递,如下图所示
3.相关指令
1 | 在AngularJS通过\{\{\}\}和ng-bind指令来实现模型(Model)数据向视图模板(View)的绑定,模型数据通过一个内置服务$scope来提供,这个$scope是一个对象,通过为这个对象添加属性或者方法便可以在相应的视图(View)模板里访问得到。 |
作用域
通常AngularJS中应用(App)是由若干个视图(View)组合成而成的,而视图(View)又都是HTML元素,并且HTML元素是可以互相嵌套的,另一方面视图都隶属于某个控制器(Controller),进而控制器之间也必然会产生嵌套关系。
每个控制器(Controller)又都对应一个模型(Model)也就是$scope对象,不同层级控制器(Controller)下的$scope便产生了作用域。
1.根作用域
一个AngularJS的应用(App)在启动时会自动创建一个根作用域$rootScope,这个根作用域在整个应用范围(ng-app所在标签以内)都是可以被访问到的。
2.子作用域
通过ng-controller指令可以创建一个子作用域,新建的作用域可以访问其父作用域的数据。
angular依赖注入的原理解析
通过构造函数的参数的名字来推断依赖的服务名称,通过toString()来找到这个定义的function对应的字符串,然后利用正则表达式去解析其中的参数,再去依赖映射取到对应的依赖,实例化之后传入。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17function controller(callback){
var scope = '小明';
var age = 23;
//判断用户传入参数的名字
var str = callback.toString();
var arr = str.split(/\(|\)/);
var arrName = arr[1];
if(arrName=='scope'){
callback(scope);
}else if(arrName=='age'){
callback(age)
}
}
//依赖注入
controller(function(scope){
console.log(scope);//小明
})