介绍
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);//小明
   })
