转载的关于AngularJs的总结

1前言

前端技术的发展是如此之快,各种优秀技术,优秀框架的出现简直让人目不暇接,紧跟时代潮流,学习掌握新知识自然是不敢怠慢。

AngularJS是谷歌在维护,其在国外已经十分火热,可是国内的使用情况却有不小的差距,参考文献/网络文章也很匮乏。这里便将我学习AngularJS写成文档,一方面作为自己学习路程上的记录,另一方面也给有兴趣的同学一些参考。

首先我自己也是一名学习者,会以学习者的角度来整理我的行文思路,这里可能只是些探索,有理解或是技术上的错误还请大家指出;其次我特别喜欢编写小例子来把一件事情说明白,故在文中会尽可能多的用示例加代码讲解,我相信这会是一种比较好的方式;最后,我深知AngularJS的使用方式跟的jquery的的使用方式有很大不同,在大家都有的jquery的,电话分机经验的条件下对于角的学习会困难重重,不过我更相信在大家的坚持下,能够快速的学好AngularJS,至少咱也能深入了解到AngularJS的基本思想,对咱们以后自己的插件开发,项目开发都会有很大的启示。

2 AngularJS概述

2.1 AngularJS是什么?

AngularJs(后面就简称NG了)是一个用于设计动态的网络应用的结构框架。首先,它是一个框架,不是类库,是像EXT一样提供一整套方案用于设计网络应用。它不仅仅是一个JavaScript的的框架,因为它的核心其实是对HTML标签的增强。

何为HTML标签增强其实就是使你能够用标签完成一部分页面逻辑,具体方式就是通过自定义标签,自定义属性等,这些HTML原生没有的标签/属性在NG中有一个名字:指令(指令)。后面会详细介绍。那么,什么又是动态的网络应用呢?与传统的网络系统相区别,网络应用能为用户提供丰富的操作,能够随用户操作不断更新视图而不进行URL跳转.ng官方也声明它更适用于开发CRUD应用,即数据操作比较多的应用,而非是游戏或图像处理类应用。

为了实现这些,NG引入了一些非常棒的特性,包括模板机制,数据绑定,模块,指令,依赖注入,路由。通过数据与模板的绑定,能够让我们摆脱繁琐的DOM操作,而将注意力集中在业务逻辑上。

源地址:https://blog.csdn.net/weixin_33178524/article/details/79179597

  另外一个疑问,NG是MVC框架吗?还是MVVM框架?官网有提到纳克的设计采用了MVC的基本思想,而又不完全是MVC,因为在书写代码时我们确实是在用NG-控制器这个指令(起码从名字上看,是MVC吧),但这个控制器处理的业务基本上都是与图进行交互,这么看来又很接近MVVM让我们把目光移到官网那个非醒目的标题上:“AngularJS - 超级英雄JavaScript MVW框架”。

2.2 AngularJS简单介绍

AngularJS重新定义了前端应用的开发方式。面对HTML和JavaScript的之间的界线,它

非但不畏缩不前,反而正面出击,提出了有效的解决方案。

很多前端应用的开发框架,比如骨干,EmberJS等,都要求开发者继承此框架特有的一些JavaScript的的对象。这种方式有其长处,但它不必要地污染了开发者自己代码的对象空间,还要求开发者去了解内存里那些抽象对象。尽管如此我们还是接受了这种方式,因为网络最初的设计无法提供我们今天所需的交互性,于是我们需要框架,来帮我们填补JavaScript的HTML的和之间的鸿沟。而且有了它,你不用再“直接”操控DOM,只要给你的DOM注上的元数据(即AngularJS里的指令们),然后让AngularJS来帮你操纵DOM。同时,AngularJS不依赖(也不妨碍)任何其他的框架。你甚至可以基于其它的框架来开发AngularJS应用。

API地址:http//docs.angularjs.org/api/ ;

AngularJS在github上的中文粗译版地址:https://github.com/basestyle/angularjs-cn。

2.3什么时候该用AngularJS

AngularJS是一个MV *框架,最适合开发客户端的单页面应用。它不是个功能库,而是用来开发动态网页的框架。它专注于扩展HTML的功能,提供动态数据绑定(数据绑定) ,而且它能跟其它框架(如jQuery的)合作融洽。

如果你要开发的是单页应用,AngularJS就是你的上上之选.Gmail,Google Docs,Twitter和Facebook这样的应用,都很能发挥AngularJS的长处。但是像游戏开发之类对DOM进行大量操纵,又或者单纯需要极高运行速度的应用,就不是AngularJS的用武之地了。

3 AugularJS特性

AngularJS是一个新出现的强大客户端技术,提供给大家的一种开发强大应用的方式。这种方式利用并且扩展HTML,CSS和JavaScript的,并且弥补了它们的一些非常明显的不足。本应该使用HTML来实现而现在由它开发的动态一些内容。

AngularJS有五个最重要的功能和特性:

3.1特性一:双向的数据绑定

数据绑定可能是AngularJS最酷最实用的特性。它能够帮助你避免书写大量的初始代码从而节约开发时间。一个典型的网络应用可能包含了80%的代码用来处理,查询和监听DOM。数据绑定是的代码更少,你可以专注于你的应用。

我们想象一下模型是你的应用中的简单事实。你的模型是你用来读取或者更新的部分。数据绑定指令提供了你的模型投射到视图的方法。这些投射可以无缝的,毫不影响的应用到网络应用中。

传统来说,当模型变化了。开发人员需要手动处理DOM元素并且将属性反映到这些变化中。这个一个双向的过程。一方面,模型变化驱动了DOM中元素变化,另一方面,DOM元素的变化也会影响到模型。这个在用户互动中更加复杂,因为开发人员需要处理和解析

这些互动,然后融合到一个模型中,并且更新视图。这是一个手动的复杂过程,当一个应用非常庞大的时候,将会是一件非常费劲的事情。

这里肯定有更好的解决方案!那就是AngularJS的双向数据绑定,能够同步DOM和型号等等。

这里有一个非常简单的例子,用来演示一个输入输入框和

元素的双向绑定(例01):

<!doctype html>

  

    

  

光引入还不够,我们还需在模块声明中注入对ngRoute的依赖,如下:

var app = angular.module('MyApp', ['ngRoute']);  

完成了这些,我们就可以在模板或是controller中使用上面的服务和指令了。下面我们需要定义一个路由表。

  第二步:定义路由表

  $routeProvider提供了定义路由表的服务,它有两个核心方法,when(path,route)和otherwise(params),先看一下核心中的核心when(path,route)方法。

  when(path,route)方法接收两个参数,path是一个string类型,表示该条路由规则所匹配的路径,它将与地址栏的内容($location.path)值进行匹配。如果需要匹配参数,可以在path中使用冒号加名称的方式,如:path为/show/:name,如果地址栏是/show/tom,那么参数name和所对应的值tom便会被保存在$routeParams中,像这样:{name : tom}。我们也可以用*进行模糊匹配,如:/show*/:name将匹配/showInfo/tom。

  route参数是一个object,用来指定当path匹配后所需的一系列配置项,包括以下内容:

l controller //function或string类型。在当前模板上执行的controller函数,生成新的scope;

l controllerAs //string类型,为controller指定别名;

l template //string或function类型,视图z所用的模板,这部分内容将被ngView引用;

l templateUrl //string或function类型,当视图模板为单独的html文件或是使用了定义模板时使用;

l resolve //指定当前controller所依赖的其他模块;

l redirectTo //重定向的地址。

最简单情况,我们定义一个html文件为模板,并初始化一个指定的controller:

function emailRouteConfig($routeProvider){

    $routeProvider.when('/show', {

        controller:ShowController,

        templateUrl:'show.html'

    })。

    当( '/ PUT /:名称',{

       controller:PutController,

       templateUrl:'put.html'

    });  

};  

否则(PARAMS)方法对应路径匹配不到时的情况,这时候我们可以配置一个redirectTo参数,让它重定向到404页面或者是首页。

  第三步:在主视图模板中指定加载子视图的位置

  我们的单页面程序都是局部刷新的,那这个“局部”是哪里呢,这就轮到ngView出马了,只需在模板中简单的使用此指令,在哪里用,哪里就是“局部”。例如:

或:   

我们的子视图将会在此处被引入进来。完成这三步后,你的程序的路由就配置好了。

4.9.3路由示例

下面我们将用一个例子(例09)来说明路由的使用方式及步骤:

1.为demoApp添加一个路由,代码如下:

demoApp.config(['$ routeProvider',function($ routeProvider){  

$ routeProvider.when('/ list',{  

templateUrl:'route / list.html',  

  controller:'routeListController'

})。when('/ list /:id',{  

  templateUrl:'route / detail.html',

   controller:'routeDetailController'

  })。除此以外({  

        redirectTo:'/ list'  

     });  

}]);

/ list对应为:route / list.html页面,显示用户列表; / list /:id对应于route / detail.html页面,显示用户详细信息。

2.为list.html和detail.html分别声明控制器:routeListController和routeDetailController。

demoApp.controller('routeListController',function($ scope){  

$ scope.users = [{userId:“zhangsan”,userName:“张三”,userInfo:“我是张三,我为自己带盐!”},

{用户名: “丽丝”,用户名: “李四”,USERINFO: “我是李四,我为卿狂”},

{用户名: “woshishui”,用户名: “我是谁”,USERINFO: “我是谁我是谁我是谁!!”}];

 

});  

demoApp.controller('routeDetailController',function($ scope,$ routeParams,userService){  

    $ scope.userDetail = userService.getUser($ routeParams.id);

});

routeDetailController中如上面提到的一样,注入了userService服务,在这里直接拿来用。

3.创建list.html和detail.html页面,代码如下:


  

路线:List.html(用户列表页面)  

      

  •   

          {{user.userName}}   

      


     

    路线:detail.html(用户详细信息页面)  

    用户名: {{userDetail.userName}}

    <跨度>用户ID:{{userDetail.userId}} <跨度>用户名:{{userDetail.userName}}

    用户简介:<跨度> {{userDetail.userInfo}}

    返回  

    4.路由局部刷新位置:

    AngularJS路由(路线)示例  

    4.10 NG动画效果

    4.10.1 NG动画效果简介

    NG动画效果,现在可以通过CSS3或者是JS来实现,如果是通过JS来实现的话,需要其他JS库(比如JQuery的)来支持,实际上底层实现还是靠其他JS库,只是NG将其封装了,

    使其更易使用。

    NG动画效果包含以下几种:

    • 输入:元素添加到DOM中时执行动画;
    • 离开:元素从DOM删除时执行动画;
    • 移动:移动元素时执行动画;
    • beforeAddClass:在给元素添加类之前执行动画;
    • addClass:在给元素添加类时执行动画;
    • beforeRemoveClass:在给元素删除类之前执行动画;
    • removeClass:在给元素删除CLASS时执行动画。

    其相关参数为:

    var ngModule = angular.module('YourApp',['ngAnimate']);

      demoApp.animation('。my-crazy-animation',function(){

    返回{

       输入:function(element,done){

      //在此处运行动画,并在动画完成时调用done

            返回功能(已取消){

              //动画时会调用此(可选)函数

              //完成或取消动画时(取消动画)

              如果取消,// flag将被设置为true)。

            };

          },

          离开:function(element,done){},

          move:function(element,done){},

          //在添加类之前可以触发的动画

          beforeAddClass: function(element, className, done) { },

          //animation that can be triggered after the class is added

          addClass: function(element, className, done) { },

          //animation that can be triggered before the class is removed

          beforeRemoveClass: function(element, className, done) { },

          //animation that can be triggered after the class is removed

          removeClass: function(element, className, done) { }

        };

      });

    4.10.2 动画效果示例

    下面我们来看下DEMO中的例子(例10)。

    1.首先,我们在demoApp下定义一个动画效果,匹配CLASS:” .border-animation”

    /*定义动画*/

    demoApp.animation('.border-animation', function(){ 

    return{ 

    beforeAddClass : function (element, className, done) { 

    $(element).stop().animate({

    'border-width':1

    },2000, function() {

    done(); 

    });

    }, 

    removeClass : function (element ,className ,done ) { 

    $(element).stop().animate({

    'border-width':50

    },3000, function() {

    done(); 

    });

    }; 

    });

    动画效果的含义就是:在匹配CLASS为边界的动画的元素添加一个CLASS之前使其边框的宽度在2秒内变为1PX;并在其移除一个CLASS时使其边框的宽度在3秒内变为50像素。

    2.视图中的代码如下(主要,其他相关样式请查看例子代码):

    更改

    NG-显示为假时会为其加上“NG隐藏“的CLASS; NG-显示为真时会为其移除“NG隐藏“的CLASS,从而触发动画效果。

    3.其他代码:

    demoApp.controller(“test10Controller”,function($ scope,$ animate){

    $ scope.testShow = true;

    });

    5功能演示

    略(详情请看AngularJS / demo WEB演示)

    6 AngularJS进阶

    6.1数据绑定原理研究

    角用户都想知道数据绑定是怎么实现的你可能会看到各种各样的词汇:?$手表,$申请,$消化,脏检查......它们是什么它们是如何工作的呢?这里我想回答这些问题,其实它们在官方的文档里都已经回答了,但是我还是想把它们结合在一起来讲,但是我只是用一种简单的方法来讲解,如果要想了解技术细节,查看源代码。

    6.1.1 AngularJS扩展事件循环

    我们的浏览器一直在等待事件,比如用户交互。假如你点击一个按钮或者在输入框里输入东西,事件的回调函数就会在JavaScript的解释器里执行,然后你就可以做任何DOM操作,等回调函数执行完毕时,浏览器就会相应地对DOM做出变化。(记住,这是个重要的概念),为了解释什么是上下文以及它如何工作,我们还需要解释更多的概念。

    6.1.2 $ watch队列

    每次你绑定一些东西到你的DOM上时你就会往$看队列里插入一条$腕表。想象一下$手表就是那个可以检测它监视的模型里时候有变化的东西。例如你有如下的代码:

    / *查看index.html * /

    用户:

    密码:

    在这里我们有个$ scope.user,他被绑定在了第一个输入框上,还有个$ scope.pass,它被绑定在了第二个输入框上,然后我们在$ watch list里面加入两个$手表。

    再看下面的例子:

    / * Controller controllers.js * /

    app.controller('MainCtrl',function($ scope){

       $ scope.foo =“Foo”;

       $ scope.world =“世界”;

    });

    / *查看index.html * /

    你好,世界 }}

    这里,即便我们在$范围上添加了两个东西,但是只有一个绑定在了DOM上,因此在这里只生成了一个$手表。

    再看下面的例子:

    / * Controller controllers.js * /

    app.controller('MainCtrl',function($ scope){

      $ scope.people = [...];

    });

    / *查看index.html * /

        

    •       {{person.name}} - {{person.age}}

        

    这里又生成了多少个$watch呢?每个person有两个(一个name,一个age),然后ng-repeat又有一个,因此10个person一共是(2 * 10) +1,也就是说有21个$watch。 

    因此,每一个绑定到了DOM上的数据都会生成一个$watch。

    那这写$watch是什么时候生成的呢? 

    当我们的模版加载完毕时,也就是在linking阶段(Angular分为compile阶段和linking阶段),Angular解释器会寻找每个directive,然后生成每个需要的$watch。

    6.1.3 $digest循环

    还记得我前面提到的扩展的事件循环吗?当浏览器接收到可以被angular context处理的事件时,$digest循环就会触发。这个循环是由两个更小的循环组合起来的。一个处理evalAsync队列,另一个处理$watch队列。 这个是处理什么的呢?$digest将会遍历我们的$watch,然后询问:

    •嘿,$watch,你的值是什么? 

    ◦是9。

    •好的,它改变过吗? 

    ◦没有,先生。

    •(这个变量没变过,那下一个)

    •你呢,你的值是多少? 

    ◦报告,是Foo。

    •刚才改变过没? 

    ◦改变过,刚才是Bar。

    •(很好,我们有DOM需要更新了)

    •继续询问直到$watch队列都检查过。

    这就是所谓的dirty-checking。既然所有的$watch都检查完了,那就要问了:有没有$watch更新过?如果有至少一个更新过,这个循环就会再次触发,直到所有的$watch都没有变化。这样就能够保证每个model都已经不会再变化。记住如果循环超过10次的话,它将会抛出一个异常,防止无限循环。当$digest循环结束时,DOM相应地变化。

    例如: 

    /*Controller  controllers.js */

    app.controller('MainCtrl',function(){

      $ scope.name =“Foo”;

      $ scope.changeFoo = function(){

          $ scope.name =“Bar”;

      }

    });

    / *查看index.html * /

    {{ 名称 }}