|
AngularJS介绍AngularJS学习文档目录1前言32AngularJS概述和使用32.1AngularJS是什么?32.2 AngularJS简单介绍42.3什么时候该用AngularJS52.4下载AngularJS并加入项目53AugularJ S特性183.1特性一:双向的数据绑定193.2特性二:模板203.3特性三:MVC213.4特性四:服务和依赖注入213 .5特性五:指令(Directives)224功能介绍224.1数据绑定224.2scopes、module、contro ller234.2.1scopes234.2.2module244.2.3ng-controller244.3ajax25 4.4表达式254.5过滤器264.5.1过滤器使用方式264.5.2ng的内置过滤器274.5.3自定义过滤器及示例294 .6指令(directive)304.6.1样式相关的指令304.6.2表单控件功能相关指令314.6.3事件绑定相关指令 344.6.4特殊的ng-src和ng-href354.6.5自定义指令示例364.7服务(service)374.7.1 服务介绍374.7.2自定义服务374.7.3管理服务的依赖关系384.7.4自定义服务示例394.8依赖注入DI414. 9路由(route)424.9.1ngRoute内容424.9.2ng的路由机制424.9.3路由示例434.10NG动 画效果454.10.1NG动画效果简介454.10.2动画效果示例465功能演示475.1数据绑定475.2控制器485 .2.1index.html内容485.2.2invoice1.js内容495.3服务(Service)505.3.1in dex.html内容505.3.2finance2.js内容515.3.3invoice2.js内容515.4调用WebA PI526AngularJS进阶526.1数据绑定原理研究526.1.1AngularJS扩展事件循环526.1.2$wat ch队列526.1.3$digest循环536.1.4如何进入angularcontext546.1.5使用$watch来监 视566.1.6总结586.2自定义指令详解586.2.1指令的编译过程586.2.2指令的使用方式及命名方法596.2.3自定 义指令的配置参数596.2.3指令的表现参数restrict等606.2.4指令的行为参数:compile和link616.2.5 指令的划分作用域参数:scope636.2.6指令间通信参数:controller和require676.3性能及调优696.3 .1性能测试696.3.2七大调优法则707总结727.1页面效果727.2委派事件(代理事件)727.2.1NG循环及事件绑 定727.2.2jQuery委派事件731前言前端技术的发展是如此之快,各种优秀技术、优秀框架的出现简直让人目不暇接,紧跟时代 潮流,学习掌握新知识自然是不敢怠慢。AngularJS是google在维护,其在国外已经十分火热,可是国内的使用情况却有不小的差距 ,参考文献/网络文章也很匮乏。这里便将我学习AngularJS写成文档,一方面作为自己学习路程上的记录,另一方面也给有兴趣的同学一 些参考。首先我自己也是一名学习者,会以学习者的角度来整理我的行文思路,这里可能只是些探索,有理解或是技术上的错误还请大家指出;其次 我特别喜欢编写小例子来把一件事情说明白,故在文中会尽可能多的用示例加代码讲解,我相信这会是一种比较好的方式;最后,我深知Angul arJS的使用方式跟jquery的使用方式有很大不同,在大家都有jquery、ext经验的条件下对于angular的学习会困难重重 ,不过我更相信在大家的坚持下,能够快速的学好AngularJS,至少咱也能深入了解到AngularJS的基本思想,对咱们以后自己的 插件开发、项目开发都会有很大的启示。2AngularJS概述和使用2.1AngularJS是什么?AngularJS诞生于2 009年,由MiskoHevery等人(一帮热血青年)创建,后为Google所收购。是一款优秀的前端JS框架,已经被用于Goo gle的多款产品当中。AngularJS有着诸多特性,最为核心的是:MVC、模块化、自动化双向数据绑定、依赖注入等等。目前企业开发 使用最多的是版本一。AngularJs(后面就简称ng了)是一个用于设计动态Web应用的结构框架。首先,它是一个框架,不是类库,是 像EXT一样提供一整套方案用于设计Web应用。它不仅仅是一个javascript框架,因为它的核心其实是对HTML标签的增强。何为 HTML标签增强?其实就是使你能够用标签完成一部分页面逻辑,具体方式就是通过自定义标签、自定义属性等,这些HTML原生没有的标签/ 属性在ng中有一个名字:指令(directive)。后面会详细介绍。那么,什么又是动态Web应用呢?与传统web系统相区别,Web 应用能为用户提供丰富的操作,能够随用户操作不断更新视图而不进行url跳转。ng官方也声明它更适用于开发CRUD应用,即数据操作比较 多的应用,而非是游戏或图像处理类应用。为了实现这些,ng引入了一些非常好的特性,包括模板机制、数据绑定、模块、指令、依赖注入、路由 。通过数据与模板的绑定,能够让我们摆脱繁琐的DOM操作,而将注意力集中在业务逻辑上。另外一个疑问,ng是MVC框架吗?还是MVV M框架?官网有提到ng的设计采用了MVC的基本思想,而又不完全是MVC,因为在书写代码时我们确实是在用ng-controller这 个指令(起码从名字上看,是MVC吧),但这个controller处理的业务基本上都是与view进行交互,这么看来又很接近MVVM。 让我们把目光移到官网那个非醒目的title上:“AngularJS—SuperheroicJavaScriptMVWFr amework”。2.2AngularJS简单介绍AngularJS重新定义了前端应用的开发方式。面对HTML和JavaScr ipt之间的界线,它非但不畏缩不前,反而正面出击,提出了有效的解决方案。很多前端应用的开发框架,比如Backbone、EmberJ S等,都要求开发者继承此框架特有的一些JavaScript对象。这种方式有其长处,但它不必要地污染了开发者自己代码的对象空间,还要 求开发者去了解内存里那些抽象对象。尽管如此我们还是接受了这种方式,因为网络最初的设计无法提供我们今天所需的交互性,于是我们需要框 架,来帮我们填补JavaScript和HTML之间的鸿沟。而且有了它,你不用再“直接”操控DOM,只要给你的DOM注上metada ta(即AngularJS里的directive们),然后让AngularJS来帮你操纵DOM。同时,AngularJS不依赖(也 不妨碍)任何其他的框架。你甚至可以基于其它的框架来开发AngularJS应用。API地址:http://docs.angularj s.org/api/http://docs.angularjs.org/api/;AngularJS在github上的中文粗译版地 址:https://github.com/basestyle/angularjs-cnhttps://github.com/bas estyle/angularjs-cn。AngularJS四大特征AngularJS的设计思想与jquery完全不同,前者操作的是 变量$scope$http,后者操作的DOM。MVC模式Angular遵循软件工程的M(数据)V(视图)C(控制器)模式,并鼓励 展现,数据,和逻辑组件之间的松耦合.通过依赖注入(dependencyinjection),Angular为客户端的Web应用带 来了传统服务端的服务,例如独立于视图的控制。因此,后端减少了许多负担,产生了更轻的Web应用。双向绑定AngularJS是建立在 这样的信念上的:即声明式编程应该用于构建用户界面以及编写软件构建,而指令式编程非常适合来表示业务逻辑。框架采用并扩展了传统HTML ,通过双向的数据绑定来适应动态内容,双向的数据绑定允许模型和视图之间的自动同步。因此,AngularJS使得对DOM的操作不再重要 并提升了可测试性。这里是区别于Jquery的,jq操作的是dom对象,angularJS操作的是变量。依赖注入依赖注入(Depen dencyInjection,简称DI)是一种设计模式,指某个对象依赖的其他对象无需手工创建,只需要“吼一嗓子”,则此对象在创 建时,其依赖的对象由框架来自动创建并注入进来,其实就是最少知识法则;模块中所有的service和provider两类对象,都可以根 据形参名称实现DI.控制器就是通过依赖注入的方式实现对服务的调用。模块化设计高内聚低耦合法则高内聚:每个模块的具体功能具体实现低耦 合:模块之间尽可能的少用关联和依赖1)官方提供的模块??ng(最核心)、ngRoute(路由)、ngAnimate(动画)2)用户 自定义的模块??angular.module(''模块名'',[])2.3什么时候该用AngularJSAngularJS是 一个MV框架,最适于开发客户端的单页面应用。它不是个功能库,而是用来开发动态网页的框架。它专注于扩展HTML的功能,提供动态 数据绑定(databinding),而且它能跟其它框架(如jQuery)合作融洽。如果你要开发的是单页应用,AngularJS就 是你的上上之选。Gmail、GoogleDocs、Twitter和Facebook这样的应用,都很能发挥AngularJS的长处 。但是像游戏开发之类对DOM进行大量操纵、又或者单纯需要极高运行速度的应用,就不是AngularJS的用武之地了。2.4下载A ngularJS并加入项目从angular提供的网址下载1.第一种方式是从angualr提供的网址上下载,如图,可以选择自己想要的 版本。https://code.angularjs.org/https://code.angularjs.org/2.例如我想下 载1.7.8的版本,我点入1.7.8的链接后,可以看到很多文件。如果我只是想下载angular.min.js的话,可以点击angu lar.min.js,点开后可以看到一堆js代码。3.随便找个文件夹,新建一个js文件,我将其命名为angular-1.7.8.m in.js(文件名随意),然后用notepad++打开,将网页上的js代码复制到angular-1.7.8.min.js中。4.复 制完后保存文件。在同一目录下创建index.html文件,测试刚刚创建的angular-1.7.8.min.js是否能够使用。用能 编辑文本文件的软件打开index.html,在index.html添加如图内容。?5.编辑完index.html后,保存文件,在浏 览器打开index.html,结果如图。说明angular-1.7.8.min.js能正常使用。?从GitHub上下载第二种方式是 直接从GitHub上下载整个项目的压缩包。Windows可选择zip包下载,linux可选择tar.gz包下载。https://g ithub.com/angular/angular.js/releaseshttps://github.com/angular/a ngular.js/releases从GitHub上下载还可以通过使用Eclipse来下载整个项目文件。打开Eclipse,选择F ile-->import。在弹出的窗口选择Git-->ProjectsfromGit。然后选择CloneURI。接下来将an gularjs在GitHub上的网址复制到URI中。选择next后,可以选择分支。接着填入一个空文件夹的路径以及选择初始的分支。最 后选择导入的方式。如果导入的方式跟我一样是选择importasgeneralproject,完成导入后可以看到Project Explorer上显示整个工程项目。3AugularJS特性AngularJS是一个新出现的强大客户端技术,提供给大家的一种开 发强大应用的方式。这种方式利用并且扩展HTML,CSS和javascript,并且弥补了它们的一些非常明显的不足。本应该使用HTM L来实现而现在由它开发的动态一些内容。AngularJS有五个最重要的功能和特性:3.1特性一:双向的数据绑定数据绑定可能是An gularJS最实用的特性。它能够帮助你避免书写大量的初始代码从而节约开发时间。一个典型的Web应用可能包含了80%的代码用来处理 ,查询和监听DOM。数据绑定是的代码更少,你可以专注于你的应用。我们想象一下Model是你的应用中的简单事实。你的Model是你用 来读取或者更新的部分。数据绑定指令提供了你的Model投射到view的方法。这些投射可以无缝的,毫不影响的应用到Web应用中。传统 来说,当model变化了。开发人员需要手动处理DOM元素并且将属性反映到这些变化中。这个一个双向的过程。一方面,model变化驱 动了DOM中元素变化,另一方面,DOM元素的变化也会影响到Model。这个在用户互动中更加复杂,因为开发人员需要处理和解析这些互动 ,然后融合到一个model中,并且更新View。这是一个手动的复杂过程,当一个应用非常庞大的时候,将会是一件非常费劲的事情。这里肯 定有更好的解决方案!那就是AngularJS的双向数据绑定,能够同步DOM和Model等等。这里有一个非常简单的例子,用来演示一个 input输入框和元素的双向绑定(例01):< head>iv>placeholder="请输入名字">
Hello,{{user.name}}! body>说明:实际效果请大家看AngularJS/demo/index.html还有一个例子,在AngularJS 中创建控制器时,将$scope对象作为参数传递。在控制器中创建的属性可以在视图中引用:-controller="myCtrl">{{carname}}运行效果:向控制器中的$scop e对象添加属性时,视图(HTML)可以访问这些属性。在视图中,您不使用前缀$scope,只需引用属性名称,如{{carname}} 。3.2特性二:模板在AngularJS中,一个模板就是一个HTML文件。但是HTML的内容扩展了,包含了很多帮助你映射mode l到view的内容。HTML模板将会被浏览器解析到DOM中。DOM然后成为AngularJS编译器的输入。AngularJS将会遍 历DOM模板来生成一些指导,即,directive(指令)。所有的指令都负责针对view来设置数据绑定。我们要理解AuguarJS 并不把模板当做String来操作。输入AngularJS的是DOM而非string。数据绑定是DOM变化,不是字符串的连接或者in nerHTML变化。使用DOM作为输入,而不是字符串,是AngularJS区别于其它的框架的最大原因。使用DOM允许你扩展指令词汇 并且可以创建你自己的指令,甚至开发可重用的组件。最大的好处是为设计师和开发者创建了一个紧密的工作流。设计师可以像往常一样开发标签, 然后开发者拿过来添加上功能,通过数据绑定将会使得这个过程非常简单。这里有一个例子,我们使用ng-repeat指令来循环图片数组并且 加入img模板,如下:functionAlbumCtrl($scope){scope.images=[{"image ":"img/image_01.png","description":"Image01description"},{ "image":"img/image_02.png","description":"Image02descriptio n"},{"image":"img/image_03.png","description":"Image03des cription"},{"image":"img/image_04.png","description":"Image 04description"},{"image":"img/image_05.png","description": "Image05description"}];} }"alt="{{image.description}}"> 这里还有一件事值得提一句,Ang ularJS并不强制你学习一个新的语法或者从你的应用中提出你的模板。3.3特性三:MVC针对客户端应用开发AngularJS吸收 了传统的MVC基本原则。MVC或者Model-View-Controll设计模式针对不同的人可能意味不同的东西。AngularJS 并不执行传统意义上的MVC,更接近于MVVM(Moodel-View-ViewModel)。Modelmodel是应用中的简单数 据。一般是简单的javascript对象。这里没有必要继承框架的classes,使用proxy对象封装或者使用特别的setter/ getter方法来访问。事实上我们处理vanillajavascript的方法就是一个非常好的特性,这种方法使得我们更少使用应用 的原型。ViewModelviewmodel是一个用来提供特别数据和方法从而维护指定view的对象。viewmodel是$scop e的对象,只存在于AnguarJS的应用中。$scope只是一个简单的js对象,这个对象使用简单的API来侦测和广播状态变化。Co ntrollercontroller负责设置初始状态和参数化$scope方法用以控制行为。需要指出的controller并不保存状 态也不和远程服务互动。Viewview是AngularJS解析后渲染和绑定后生成的HTML。这个部分帮助你创建Web应用的架构。 $scope拥有一个针对数据的参考,controller定义行为,view处理布局和互动。3.4特性四:服务和依赖注入Angul arJS服务其作用就是对外提供某个特定的功能。AngularJS拥有内建的依赖注入(DI)子系统,可以帮助开发人员更容易的开发,理 解和测试应用。DI允许你请求你的依赖,而不是自己找寻它们。比如,我们需要一个东西,DI负责找创建并且提供给我们。为了而得到核心的A ngularJS服务,只需要添加一个简单服务作为参数,AngularJS会侦测并且提供给你:functionEditCtrl($ scope,$location,$routeParams){//Somethingcleverhere...}你也可 以定义自己的服务并且让它们注入:angular.module(''MyServiceModule'',[]).factory(''n otify'',[''$window'',function(win){returnfunction(msg){win. alert(msg);};}]);functionmyController(scope,notifyService){ scope.callNotify=function(msg){notifyService(msg);};}myCont roller.$inject=[''$scope'',''notify''];3.5特性五:指令(Directives)指令是我个 人最喜欢的特性。你是不是也希望浏览器可以做点儿有意思的事情?那么AngularJS可以做到。指令可以用来创建自定义的标签。它们可以 用来装饰元素或者操作DOM属性。可以作为标签、属性、注释和类名使用。这里是一个例子,它监听一个事件并且针对的更新它的$scope ,如下:myModule.directive(''myComponent'',function(mySharedService) {return{restrict:''E'',controller:function($scope,$attrs,m ySharedService){$scope.$on(''handleBroadcast'',function(){$sc ope.message=''Directive:''+mySharedService.message;});},rep lace:true,template:''''};});然后,你可以使用这个自定义的directive来使用:< my-componentng-model="message">使用一系列的组件来创建你自己的应用将 会让你更方便的添加,删除和更新功能。4功能介绍4.1数据绑定AngularJS的双向数据绑定,意味着你可以在Mode(JS)中 改变数据,而这些变动立刻就会自动出现在View上,反之亦然。即:一方面可以做到model变化驱动了DOM中元素变化,另一方面也可以 做到DOM元素的变化也会影响到Model。在我们使用jQuery的时候,代码中会大量充斥类似这样的语句:varval=$(‘ #id’).val();$(‘#id’).html(str);等等,即频繁的DOM操作(读取和写入),其实我们的最终目的并不是要 操作DOM,而是要实现业务逻辑。ng的绑定将让你摆脱DOM操作,只要模板与数据通过声明进行了绑定,两者将随时保持同步,最新的数据会 实时显示在页面中,页面中用户修改的数据也会实时被记录在数据模型中。从View到Controller再到View的数据交互(例01) :……placeholder="请输入名称"/>Hello,{{user.name}}!……关键:ng-app、ng-mo del和{{user.name}}首先:元素的ng-app属性。标识这个DOM里面的内容将启用Angul arJS应用。其次:告诉AngularJS,对页面上的“user.name”这个Model进行双向数据绑定。第三:告诉Angul arJS,在“{{user.name}}”这个指令模版上显示“user.name”这个Model的数据。从Server到Cont roller再到View的数据交互(例02):……er="demoController">led="disabled"/>er()">AJAX获取名字……demoApp.controller("demoController",function ($http,$scope){$scope.getAjaxUser=function(){//$http.get ({url:"../xxx.action"}).success(function(data){//$scope.user=da ta;//});$scope.user={"name":"从JOSN中获取的名称","age":22};};} );改变$scope中的user,View也会自动更新。4.2scopes、module、controller4.2.1sc opes$scope是一个把view(一个DOM元素)连结到controller上的对象。在我们的MVC结构里,这个$scope 将成为model,它提供一个绑定到DOM元素(以及其子元素)上的excecutioncontext。尽管听起来有点复杂,但$ scope实际上就是一个JavaScript对象,controller和view都可以访问它,所以我们可以利用它在两者间传递信息 。在这个$scope对象里,我们既存储数据,又存储将要运行在view上的函数。每一个Angular应用都会有一个$rootS cope。这个$rootScope是最顶级的scope,它对应着含有ng-app指令属性的那个DOM元素。app.run( function($rootScope){$rootScope.name="张三";});如果页面上没有明确设定$sc ope,Angular就会把数据和函数都绑定到这里,第一部分中的例子就是靠这一点成功运行的。这样,我们就可以在view的任何 地方访问这个name属性,使用模版表达式{{}},像这样:{{name}}4.2.2module首先需要明确一下模板的概 念。在我还不知道有模板这个东西的时候,曾经用js拼接出很长的HTML字符串,然后append到页面中,这种方式想想真是又土又笨。后 来又看到可以把HTML代码包裹在一个将当前元素的内容添加到有ng-transc lude属性的这个DIV下,默认是隐藏的。3.Controller信息:demoApp.controller("test7Cont roller",function($scope){$scope.title=''个人简介'';$scope.text=''大家 好,我正在研究AngularJs,欢迎大家与我交流。'';$scope.updateInfo=function(){$scop e.title=''个人信息'';$scope.text=''大家好,今天天气真好!'';}});4.指令使用方式(View信息) 为:{{text}}Etitle指向Control ler中的$scope.title。注意命名方式:指令名为userInfo,对应的标签为user-info。4.7服务(serv ice)4.7.1服务介绍服务这个概念其实并不陌生,在其他语言中如java便有这样的概念,其作用就是对外提供某个特定的功能,如 消息服务,文件压缩服务等,是一个独立的模块。ng的服务是这样定义的:Angularservicesaresingletons objectsorfunctionsthatcarryoutspecifictaskscommontoweb apps.它是一个单例对象或函数,对外提供特定的功能。首先是一个单例,即无论这个服务被注入到任何地方,对象始终只有一个实例。其次 这与我们自己定义一个function然后在其他地方调用不同,因为服务被定义在一个模块中,所以其使用范围是可以被我们管理的。ng的避 免全局变量污染意识非常强。ng提供了很多内置的服务,可以到API中查看http://docs.angularjs.org/api /。知道了概念,我们来拉一个service出来溜溜,看看到底是个什么用法。我们在controller中直接声明$locati on服务,这依靠ng的依赖注入机制。$location提供地址栏相关的服务,我们在此只是简单的获取当前的地址。服务的使用是如此简 单,我们可以把服务注入到controller、指令或者是其他服务中。4.7.2自定义服务如同指令一样,系统内置的服务以$开头, 我们也可以自己定义一个服务。定义服务的方式有如下几种:使用系统内置的$provide服务;使用Module的factory方法;使 用Module的service方法。下面通过一个小例子来分别试验一下。我们定义一个名为remoteData服务,它可以从远程获取 数据,这也是我们在程序中经常使用的功能。不过我这里没有远程服务器,就写死一点数据模拟一下。//使用$provide来定义vara pp=angular.module(''MyApp'',[],function($provide){$provide.f actory(''remoteData'',function(){vardata={name:''n'',value: ''v''};returndata;});});//使用factory方法app.factory(''remoteData'', function(){vardata={name:''n'',value:''v''};returndata; });//使用service方法app.service(''remoteData'',function(){this.name =''n'';this.value=''v'';});Module的factory和$provide的factory方法是一模一 样的,从官网文档看它们其实就是一回事。至于Module内部是如何调用的,我此处并不打算深究,我只要知道怎么用就好了。再看Modul e的service方法,它没有return任何东西,是因为service方法本身返回一个构造器,系统会自动使用new关键字来创建出 一个对象。所以我们看到在构造器函数内可以使用this,这样调用该服务的地方便可以直接通过remoteData.name来访问数据了 。4.7.3管理服务的依赖关系服务与服务中间可以有依赖关系,例如我们这里定义一个名为validate的服务,它的作用是验证数据 是否合法,它需要依赖我们从远程获取数据的服务remoteData。代码如下:在factory的参数中,我们可以直接传入服务r emoteData,ng的依赖注入机制便帮我们做好了其他工作。不过一定要保证这个参数的名称与服务名称一致,ng是根据名称来识别的。 若参数的名次与服务名称不一致,你就必须显示的声明一下,方式如下:app.factory(''validate'',[''remoteD ata'',function(remoteDataService){returnfunction(){if(rem oteDataService.name==''n''){alert(''验证通过'');}};}]);我们在controlle r中注入服务也是同样的道理,使用的名称需要与服务名称一致才可以正确注入。否则,你必须使用$inject来手动指定注入的服务。比如: functiontestC(scope,rd){scope.getData=function(){alert('' name:''+rd.name+''value:''+rd.value);}}testC.$inject=[''$ scope'',''remoteData''];在controller中注入服务,也可以在定义controller时使用数组作为第二 个参数,在此处把服务注入进去,这样在函数体中使用不一致的服务名称也是可以的,不过要确保注入的顺序是一致的,如:app.contro ller(''testC'',[''$scope'',''remoteData'',function($scope,rd){$s cope.getData=function(){alert(''name:''+rd.name+''value: ''+rd.value);}}]);4.7.4自定义服务示例接下来让我们看下例子(例08自定义服务)代码,自定义userS ervice服务:demoApp.factory(''userService'',[''$http'',function($http ){vardoGetUser=function(userId,path){//return$http({// method:''JSONP'',//url:path//});/手动指定数据/vardata={userId :"woshishui",userName:"我是谁",userInfo:"我是谁!我是谁!"};;if(user Id==''zhangsan''){data={userId:"zhangsan",userName:"张三", userInfo:"我是张三,我为自己"};}elseif(userId==''lisi''){data={ userId:"lisi",userName:"李四",userInfo:"我是李四,我为卿狂!"};}retur ndata;}return{/userService对外暴露的函数,可有多个/getUser:function (userId){returndoGetUser(userId,''../xxx/xxx.action'');}};}]) ;我们创建了一个只有一个方法的userService,getUser为这个服务从后台获取用户信息的函数,并且对外暴露。当然,由于这 是一个静态的例子,无法访问后台,那么我们便制定其返回的数据。然后我们把这个服务添加到我们的controller中。我们建立一个co ntroller并加载(或者注入)userService作为运行时依赖,我们把service的名字作为参数传递给controlle r函数:demoApp.controller("test8Controller",function($scope,user Service){/文章信息/$scope.articles=[{title:"爱飞像风",userId:" zhangsan",userName:"张三"},{title:"无法停止的雨",userId:"lisi",u serName:"李四"}];$scope.showUserInfo=false;//显示作者详细信息开关$scope .currentUser={};//当前选中的作者$scope.getUserInfo=function(userI d){$scope.currentUser=userService.getUser(userId);//调用userS ervice的getUser函数$scope.showUserInfo=true;setTimeout(function (){//定时器:隐藏作者详细信息$scope.showUserInfo=false;},3000);}});我们的 userService注入到我们的test8Controller后,我们就可以像使用其他服务(我们前面提到的$http服务)一样的 使用userService了。相关的HTML代码如下:/ViewHTML/inarticles">{{article_.title}} | oid(0);"ng-click="getUserInfo(article_.userId)">{{article_.user Name}} | | ......用户ID:{{cu rrentUser.userId}} 用户名:{{currentUser.userName}} 用户简介:{{cu rrentUser.userInfo}} 4.8依赖注入DI通过依赖注入,ng想要推崇一种声明式的开发方式, 即当我们需要使用某一模块或服务时,不需要关心此模块内部如何实现,只需声明一下就可以使用了。在多处使用只需进行多次声明,大大提高可复 用性。比如我们的controller,在定义的时候用到一个$scope参数。app.controller(''testC'',fun ction($scope){});如果我们在此处还需操作其他的东西,比如与浏览器地址栏进行交互。我们只需再多添一个参数$loca tion进去:app.controller(''testC'',function($scope,$location){});这样便可 以通过$location来与地址栏进行交互了,我们仅仅是声明了一下,所需的其他代码,框架已经帮我们注入了。我们很明显的感觉到了这个 函数已经不是常规意义上的javascript函数了,在常规的函数中,把形参换一个名字照样可以运行,但在此处若是把$scope换成别 的名字,程序便不能运行了。因为这是已经定义好的服务名称。这便是依赖注入机制。顺理成章的推断,我们可以自己定义模块和服务,然后在需要 的地方进行声明,由框架来替我们注入。来看下我们如何定义一个服务:app.factory(''tpls'',function(){ return[''tpl1'',''tpl2'',''tpl3'',''tpl4''];});看上去相当简单,是因为我在这里仅仅是直接返 回一个数组。在实际应用中,这里应该是需要向服务器发起一个请求,来获取到这些模板们。服务的定义方式有好几种,包括使用provider 方法、使用factory方法,使用service方法。它们之间的区别暂且不关心。我们现在只要能创建一个服务出来就可以了。我使用了f actory方法。一个需要注意的地方是,框架提供的服务名字都是由$开头的,所以我们自己定义的最好不要用$开头,防止发生命名冲突。定 义好一个服务后,我们就可以在控制器中声明使用了,如下:app.controller(''testC'',function($sco pe,tpls){$scope.question=questionModel;$scope.nowTime=new Date().valueOf();$scope.templates=tpls;//赋值到$scope中$scope.a ddOption=function(){varo={content:''''};$scope.question .options.push(o);};$scope.delOption=function(index){$scope .question.options.splice(index,1);};});此时,若在模板中书写如下代码,我们便可以获取到服 务tpls所提供的数据了:模板:plates">{{t}} 4.9路由(route)在谈路由机制前有必要先提一下现在比 较流行的单页面应用,就是所谓的singlepageAPP。为了实现无刷新的视图切换,我们通常会用ajax请求从后台取数据,然后 套上HTML模板渲染在页面上,然而ajax的一个致命缺点就是导致浏览器后退按钮失效,尽管我们可以在页面上放一个大大的返回按钮,让用 户点击返回来导航,但总是无法避免用户习惯性的点后退。解决此问题的一个方法是使用hash,监听hashchange事件来进行视图切换 ,另一个方法是用HTML5的historyAPI,通过pushState()记录操作历史,监听popstate事件来进行视图切换 ,也有人把这叫pjax技术。基本流程如下:如此一来,便形成了通过地址栏进行导航的深度链接(deeplinking),也就是我们所 需要的路由机制。通过路由机制,一个单页应用的各个视图就可以很好的组织起来了。4.9.1ngRoute内容ng的路由机制是靠ng Route提供的,通过hash和history两种方式实现了路由,可以检测浏览器是否支持history来灵活调用相应的方式。ng的 路由(ngRoute)是一个单独的模块,包含以下内容:服务$routeProvider用来定义一个路由表,即地址栏与视图模板的映射 服务$routeParams保存了地址栏中的参数,例如{id:1,name:''tom''}服务$route完成路由匹配,并 且提供路由相关的属性访问及事件,如访问当前路由对应的controller指令ngView用来在主视图中指定加载子视图的区域以上内 容再加上$location服务,我们就可以实现一个单页面应用了。下面来看一下具体如何使用这些内容。4.9.2ng的路由机制第一 步:引入文件和依赖ngRoute模块包含在一个单独的文件中,所以第一步需要在页面上引入这个文件,如下:http://code.angularjs.org/1.2.8/angular.min.js">">订单:数量:y"> 单价:> 总价:{{qtycost|currency}}
| |