4.8依赖注入DI

通过依赖注入,ng想要推崇一种声明式的开发方式,即当我们需要使用某一模块或服务时,不需要关心此模块内部如何实现,只需声明一下就可以使用了。在多处使用只需进行多次声明,大大提高可复用性。

  比如我们的controller,在定义的时候用到一个$scope参数。

app.controller('testC',function($scope){});  

如果我们在此处还需操作其他的东西,比如与浏览器地址栏进行交互。我们只需再多添

一个参数$location进去:

app.controller('testC',function($scope,$location){});  

这样便可以通过$location来与地址栏进行交互了,我们仅仅是声明了一下,所需的其他代码,框架已经帮我们注入了。我们很明显的感觉到了这个函数已经不是常规意义上的javascript函数了,在常规的函数中,把形参换一个名字照样可以运行,但在此处若是把$scope换成别的名字,程序便不能运行了。因为这是已经定义好的服务名称。

这便是依赖注入机制。顺理成章的推断,我们可以自己定义模块和服务,然后在需要的地方进行声明,由框架来替我们注入。

来看下我们如何定义一个服务:

app.factory('tpls',function(){

return ['tpl1','tpl2','tpl3','tpl4'];

});  

看上去相当简单,是因为我在这里仅仅是直接返回一个数组。在实际应用中,这里应该是需要向服务器发起一个请求,来获取到这些模板们。服务的定义方式有好几种,包括使用provider方法、使用factory方法,使用service方法。它们之间的区别暂且不关心。我们现在只要能创建一个服务出来就可以了。我使用了factory方法。一个需要注意的地方是,框架提供的服务名字都是由$开头的,所以我们自己定义的最好不要用$开头,防止发生命名冲突。

定义好一个服务后,我们就可以在控制器中声明使用了,如下:

app.controller('testC',function($scope,tpls){

$scope.question = questionModel;

$scope.nowTime = new Date().valueOf();

$scope.templates = tpls; //赋值到$scope中

$scope.addOption = function(){

var o = {content:''};

$scope.question.options.push(o);

};

$scope.delOption = function(index){

$scope.question.options.splice(index,1);

};

});  

此时,若在模板中书写如下代码,我们便可以获取到服务tpls所提供的数据了:

模板:

<a href="javascript:void(0);" target="_blank" rel="nofollow">

4.9路由route

在谈路由机制前有必要先提一下现在比较流行的单页面应用,就是所谓的single page APP。为了实现无刷新的视图切换,我们通常会用ajax请求从后台取数据,然后套上HTML模板渲染在页面上,然而ajax的一个致命缺点就是导致浏览器后退按钮失效,尽管我们可以在页面上放一个大大的返回按钮,让用户点击返回来导航,但总是无法避免用户习惯性的点后退。解决此问题的一个方法是使用hash,监听hashchange事件来进行视图切换,另一个方法是用HTML5的history API,通过pushState()记录操作历史,监听popstate事件来进行视图切换,也有人把这叫pjax技术。基本流程如下:

如此一来,便形成了通过地址栏进行导航的深度链接(deeplinking ),也就是我们所需要的路由机制。通过路由机制,一个单页应用的各个视图就可以很好的组织起来了。

4.9.1 ngRoute内容

  ng的路由机制是靠ngRoute提供的,通过hash和history两种方式实现了路由,可以检测浏览器是否支持history来灵活调用相应的方式。ng的路由(ngRoute)是一个单独的模块,包含以下内容:

l 服务$routeProvider用来定义一个路由表,即地址栏与视图模板的映射

l 服务$routeParams保存了地址栏中的参数,例如{id : 1, name : 'tom'}

l 服务$route完成路由匹配,并且提供路由相关的属性访问及事件,如访问当前路由对应的controller

l 指令ngView用来在主视图中指定加载子视图的区域

 以上内容再加上$location服务,我们就可以实现一个单页面应用了。下面来看一下具体如何使用这些内容。

4.9.2 ng的路由机制

  第一步:引入文件和依赖

  ngRoute模块包含在一个单独的文件中,所以第一步需要在页面上引入这个文件,如下:

<script src="http://code.angularjs.org/1.2.8/angular.min.js" rel="nofollow"/>

<script src="http://code.angularjs.org/1.2.8/angular-route.min.js" rel="nofollow"/>  

光引入还不够,我们还需在模块声明中注入对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文件或是使用了<script type="text/ng-template">定义模板时使用;

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

l redirectTo //重定向的地址。

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

function emailRouteConfig($routeProvider){

$routeProvider.when('/show', {

controller: ShowController,

templateUrl: 'show.html'

}).

when('/put/:name',{

controller: PutController,

templateUrl: 'put.html'

});

};  

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

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

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

<div ng-view></div>  或:<ng-view></ng-view>  

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

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'

}).otherwise({

redirectTo: '/list'

});

}]);

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

2.为list.html和detail.html分别声明Controller:routeListController和routeDetailController。

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

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

{userId:"lisi",userName:"李四",userInfo:"我是李四,我为卿狂!"},

{userId:"woshishui",userName:"我是谁",userInfo:"我是谁!我是谁!我是谁!"}];

});

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

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

});

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

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

<hr/>

<h3>Route : List.html(用户列表页面)</h3>

<ul>

<li ng-repeat="user in users">

<a href="http://m.cnblogs.com/142260/3817063.html?full=1#/list/{{ user.userId }}" target="_blank" rel="nofollow">

</li>

</ul>

<hr/>

<h3>Route : detail.html(用户详细信息页面)</h3>

<h3>用户名:<span style="color: red;">{{userDetail.userName}}</span></h3>

<div>

<span>用户ID:{{userDetail.userId}}</span><span>用户名:{{userDetail.userName}}</span>

</div>

<div>

用户简介:<span>{{userDetail.userInfo}}</span>

</div>

<div>

<a href="http://m.cnblogs.com/142260/3817063.html?full=1#/list" target="_blank" rel="nofollow">返回</a>

</div>

4. 路由局部刷新位置:

<h1>AngularJS路由(Route) 示例</h1>

<div ng-view></div>

4.10 NG动画效果

4.10.1 NG动画效果简介

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

使其更易使用。

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

  • enter:元素添加到DOM中时执行动画;
  • leave:元素从DOM删除时执行动画;
  • move:移动元素时执行动画;
  • beforeAddClass:在给元素添加CLASS之前执行动画;
  • addClass:在给元素添加CLASS时执行动画;
  • beforeRemoveClass:在给元素删除CLASS之前执行动画;
  • removeClass:在给元素删除CLASS时执行动画。

其相关参数为:

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

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

return {

enter: function(element, done) {

//run the animation here and call done when the animation is complete

return function(cancelled) {

//this (optional) function will be called when the animation

//completes or when the animation is cancelled (the cancelled

//flag will be set to true if cancelled).

};

},

leave: function(element, done) { },

move: function(element, done) { },

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

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为border-animation的元素添加一个CLASS之前使其边框的宽度在2秒内变为1PX;并在其移除一个CLASS时使其边框的宽度在3秒内变为50PX。

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

<div class="border-animation" ng-show="testShow"></div>

<a href="javascript:void(0);" target="_blank" rel="nofollow">

ng-show为false时会为其加上“ng-hide“的CLASS; ng-show为true时会为其移除“ng-hide“的CLASS,从而触发动画效果。

3.其他代码:

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

$scope.testShow = true;

});

Angular入门教程四的更多相关文章

  1. 无废话ExtJs 入门教程四[表单:FormPanel]

    无废话ExtJs 入门教程四[表单:FormPanel] extjs技术交流,欢迎加群(201926085) 继上一节内容,我们在窗体里加了个表单.如下所示代码区的第28行位置,items:form. ...

  2. PySide——Python图形化界面入门教程(四)

    PySide——Python图形化界面入门教程(四) ——创建自己的信号槽 ——Creating Your Own Signals and Slots 翻译自:http://pythoncentral ...

  3. Elasticsearch入门教程(四):Elasticsearch文档CURD

    原文:Elasticsearch入门教程(四):Elasticsearch文档CURD 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接: ...

  4. RabbitMQ入门教程(四):工作队列(Work Queues)

    原文:RabbitMQ入门教程(四):工作队列(Work Queues) 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https:/ ...

  5. JasperReports入门教程(四):多数据源

    JasperReports入门教程(四):多数据源 背景 在报表使用中,一个页面需要打印多个表格,每个表格分别使用不同的数据源是很常见的一个需求.假如我们现在有一个需求如下:需要在一个报表同时打印所有 ...

  6. WebGL入门教程(四)-webgl颜色

    前面文章: WebGL入门教程(一)-初识webgl WebGL入门教程(二)-webgl绘制三角形 WebGL入门教程(三)-webgl动画 颜色效果图: 操作步骤: 1.创建HTML5 canva ...

  7. 中文代码示例之Angular入门教程尝试

    原址: https://zhuanlan.zhihu.com/p/30853705 原文: 中文代码示例教程之Angular尝试 为了检验中文命名在Angular中的支持程度, 把Angular官方入 ...

  8. 2017-11-07 中文代码示例之Angular入门教程尝试

    "中文编程"知乎专栏原址 原文: 中文代码示例教程之Angular尝试 为了检验中文命名在Angular中的支持程度, 把Angular官方入门教程的示例代码中尽量使用了中文命名. ...

  9. Spring Cloud 入门教程(四): 分布式环境下自动发现配置服务

    前一章, 我们的Hello world应用服务,通过配置服务器Config Server获取到了我们配置的hello信息“hello world”. 但自己的配置文件中必须配置config serve ...

随机推荐

  1. 网络基础 08_NAT

    1 NAT的基本概念 为什么需要NAT IPv4地址紧缺 什么是NAT NAT(Network Address Translation) 私有IPv4地址 10.0.0.0 - 10.255.255. ...

  2. BZOJ3168. [HEOI2013]钙铁锌硒维生素(线性代数+二分图匹配)

    题目链接 https://www.lydsy.com/JudgeOnline/problem.php?id=3168 题解 首先,我们需要求出对于任意的 \(i, j(1 \leq i, j \leq ...

  3. shell脚本杀进程重启

    #!/bin/bash ID=`ps -ef | grep "abc" | grep -v "$0" | grep -v "grep" | ...

  4. sql在insert时判断有无唯一性冲突

    sql在insert时判断有无唯一性冲突,存在相同主键或唯一索引,则不创建 INSERT INTO table(field1, field2, fieldn) SELECT 'field1', 'fi ...

  5. python-Lock锁线程同步和互斥

    #!/usr/bin/python #coding=utf-8 #线程间通信的同步与互斥操作-锁 import threading a=b=0 lock=threading.Lock() def va ...

  6. jQuery插件开发之windowScroll

    回首望,曾经洋洋得意的代码现在不忍直视.曾经看起来碉堡的效果现在也能稍微弄点出来.社会在往前发展,人也得向前迈进. 参考于搜狗浏览器4.2版本首页的上下滚动效果.主要实现整个窗口的上下和左右滚动逻辑, ...

  7. UVM序列篇之二:sequence和item(上)

    无论是自驾item,穿过sequencer交通站,通往终点driver,还是坐上sequence的大巴,一路沿途观光,最终跟随导游停靠到风景点driver,在介绍如何驾驶item和sequence,遵 ...

  8. docker上安装nginx服务

    环境     1.开启一个容器,安装nginx,略过   2.假如第一步新启动没映射端口的话,重新把容器保存为镜像然后再重新运行一个新容器,不建议在一个正在运行的容器上做端口映射 docker run ...

  9. 时间格式转换成JUN.13,2017

    SimpleDateFormat sdf = new SimpleDateFormat("MMM.dd,yyyy", Locale.ENGLISH); String negotia ...

  10. DWF Toolkit on Microsoft Windows

    If you are statically linking on Windows, you need these preprocessor defines: DWFTK_STATIC DWFTK_BU ...