AngularJS入门之Services
关于AngularJS中的DI
在开始说AngularJS的Service之前,我们先来简单讲讲DI(Dependency Injection,通常中文称之为“依赖注入”)。
DI是一种软件设计模式,主要为了解决组件获取它的依赖组件的问题。DI的概念渗透在AngularJS的各个地方,AngularJS使用一个专门的子系统($injector)进行DI管理,这个过程包括了创建组件、解析、获取它的依赖组件,并将这些依赖组件回传给请求组件。
我们其实已经在不知不觉中使用DI了(比如在AngularJS自定义Directive中的出现过):
app.directive('myCurrentTime', ['$interval', 'dateFilter', function ($interval, dateFilter) {
}
上述代码片段在添加Controller时,其中$interval就是Controller中依赖注入Service的推荐方法。由于$injector的存在,对于我们只需将所需服务的名称传入我们的模块即可,底层的工作都将由$injector包办。
$injector的原理如下图:
AngularJS中使用DI添加Service的三种方法:
方式1(内联注解,推荐使用):
app.controller('myController', ['$scope', 'dateFilter', function ($scope, dateFilter) { }]);
方式2($inject注解):
var MyController = function($scope, dateFilter) {
// ...
}
MyController.$inject = ['$scope', 'dateFilter'];
someModule.controller('MyController', MyController);
方式3(隐式注解,不推荐使用):
app.controller('myController', function ($scope, dateFilter) { });
推荐使用方式1的理由是:
- 写法上比方法2更简单明了
- 比方法3更可靠(由于Javascript可以被压缩,AngularJS又是通过解析服务名称找到对应Service的,因此Javascript压缩之后AngularJS将无法找到指定的Service,但字符串不会被压缩,因此单独以字符串指定Service的名称可以避免这个问题)
使用方式1或方式2的注意点:
由于上述第二点原因,AngularJS在编译Html时,由$injector将数组中Service的名称与方法体中的Service进行一一映射。这种映射关系必须遵守由AngularJS的约定:
- 数组中Service名称的个数必须与方法体中Service名称的个数一致
- 数组中Service的顺序必须与方法体中Serivce的顺序一致
如果为了编码规范需要强制使用显式DI(也就是方式1或者方式2),可使用ng-strict-di属性,这样AngularJS在遇到隐式DI(也就是方式3)时将会报错。
示例1:
<!DOCTYPE >
<html>
<head>
<script src="/Scripts/angular.js"></script>
<script type="text/javascript">
(function () {
var app = angular.module('diTest', []); app.controller('myController1', ['$scope', function ($scope) {
}]); // 方式1 隐式DI,在指定了ng-strict-di后,将会报错
//app.controller('myController1', function ($scope) {
//}); var myController2 = function ($scope) {
};
myController2.$inject = ['$scope'];
app.controller('myController2', myController2); // 方式2 隐式DI,在指定了ng-strict-di后,将会报错
//var myController2 = function ($scope) {
//};
//app.controller('myController2', myController2);
})();
</script>
</head>
<body ng-app="diTest" ng-strict-di>
<div ng-controller="myController1 as myCtrl1">
</div> <div ng-controller="myController2 as myCtrl2">
</div>
</body>
</html>
示例1中,因为body使用了ng-strict-di属性,因此当使用方式1或者方式2的隐式DI时,AngularJS将会抛出如下错误:
AngularJS中的Services:
AngularJS提供了很多Services,常用的如$http,是集成在AngularJS和核心库中的,另外有一部分如$animate是独立的模块。由于篇幅问题,我们先以$http为例了解一下AngularJS的Service。
迄今为止我所有的AngularJS系列的文章中,所有的数据均是通过ng-init或者在$scope中初始化数组来完成的。但实际项目中,我们的数据都会从服务器获取。写个例子来演示一下这个过程。
Step 1,创建一个名为data.txt的文件,里面包含一个Json对象:
{
"students": [
{
"Name": "Jack",
"Age": 21
},
{
"Name": "Alice",
"Age": 20
},
{
"Name": "Tom",
"Age": 21
},
{
"Name": "Sophie",
"Age": 19
}
]
}
Step 2,使用$http的get方法获取data.txt的数据,并将数据赋值给$scope.students:
app.controller('myController', ['$scope', '$http', function ($scope, $http) {
$scope.students = [];
$http.get('data.txt').
success(function (data, status, headers, config) {
$scope.students = data.students;
console.log(data);
console.log(data.students);
console.log($scope.students);
}).
error(function (data, status, headers, config) {
});
}]);
Step 3,使用ng-repeat显示students的信息:
<div ng-repeat="stu in students">
<p>Name: {{stu.Name}}</p>
<p>Age: {{stu.Age}}</p>
<br />
</div>
完整的Html代码如下:
<!DOCTYPE >
<html>
<head>
<script src="/Scripts/angular.js"></script>
<script type="text/javascript">
(function () {
var app = angular.module('httpServiceTest', []); app.controller('myController', ['$scope', '$http', function ($scope, $http) {
$scope.students = [];
$http.get('data.txt').
success(function (data, status, headers, config) {
$scope.students = data.students;
console.log(data);
console.log(data.students);
console.log($scope.students);
}).
error(function (data, status, headers, config) {
});
}]);
})();
</script>
</head>
<body ng-app="httpServiceTest" ng-controller="myController">
<div ng-repeat="stu in students">
<p>Name: {{stu.Name}}</p>
<p>Age: {{stu.Age}}</p>
<br />
</div>
</body>
</html>
关于$http:
$http的基本调用格式:
$http(config).success(function(data,status,headers,config){ }).error(function(data,status,headers,config){ });
config为Json对象,完整参数说明如下:
- method{string} - HTTP方法,示例值GET、POST等
- url{string} - 请求资源的绝对或者相对路径,示例值 http://mytest.com/user/example 或 /myservice/user/example
- params{Object.<string|Object>} - URL的请求参数部分,可以直接是一个完整的字符串也可以是一个对象,对象将被自动JSon序列化(一般给Get使用)
- data{string|Object} - 请求参数内容(一般给Post使用)
- headers{Object} - Http请求的Headers
- xsrfHeaderName{string} - 防XSRF(跨站请求伪造)的Header名称
- xsrfCookieName{string} - 防XSRF的Cookie名称
- transformRequest{function(data,headersGetter)|Array.<function(data,headersGetter)>} - 自定义Http请求格式的方法
- transformResponse{function(data, headersGetter, status)|Array.<function(data, headersGetter, status)>} - 自定义Http响应格式的方法
- paramSerializer{string|function(Object):string} - 序列化params的方法
- cache{boolean|Cache} - boolean类型指定是否缓存GET请求,或者指定一个由$cacheFactory创建的缓存实例
- timeout{number|Promise} - number为请求超时时间(单位为毫秒);或者指定一个可以中断请求的promise
- withCredentials{boolean} - 是否需要证书,详见:requests with credentials
- responseType{string} - 返回类型,详见:requestType
注意:由于是入门类文章,本章中对于以上各个参数的用法不深入展开了,这部分内容今后单独开一章来讨论。
$http调用原型中,方法success和error为$http调用返回的promise,promise是由AngularJS的核心服务$q提供的一种处理异步请求的实现方式,关于promise的细节,本篇也不做展开,可参考官方文档:https://docs.angularjs.org/api/ng/service/$q。我们只需知道,由于success和error是$http方法调用返回的promise(承诺),因此在异步完成$http方法的调用完成、失败或超时后,最终必定会调用success或者error方法。
$http的调用原型看起来比较复杂,为了便于使用,AngularJS提供了$http调用的快捷方式(如$http.get, $http.post等),其基本格式如下:
$http.get('/someUrl').success(successCallback);
$http.post('/someUrl', data).success(successCallback);
$http所有方法的快捷方式(其中[config]表示config为可选参数):
- $http.get :get(url, [config])
- $http.head :head(url, [config])
- $http.post :post(url, data, [config])
- $http.put :put(url, data, [config])
- $http.delete :delete(url, [config])
- $http.jsonp :jsonp(url, [config])
- $http.patch :patch(url, data, [config])
好了,通过本篇的介绍,我们已经基本了解了DI的概念,以及AngularJS中如何使用DI来完成Service的使用,我们还重点看了一下$http以及它的使用方式,当然,关于更多$http的细节今后会单独开一篇讨论的。
如果你和我一样也是AngularJS的新手,那通过这么多天的学习后,我们已经能使用AngularJS完成一个真正的Web网站的原型的搭建了:AngularJS负责前端,数据由后端服务提供。还犹豫什么呢,赶紧自己试试吧。
参考资料
AngularJS官方文档DI:https://docs.angularjs.org/guide/di
AngularJS官方文档Service:https://docs.angularjs.org/api/ng/service
AngularJS入门之Services的更多相关文章
- AngularJS入门心得4——漫谈指令scope
上篇<AngularJS入门心得3——HTML的左右手指令>初步介绍了指令的概念和作用.已经和指令打过一个照面,就不会那么陌生了,今天主要介绍的是一个困扰了我很久终于想通的问题,这个问题与 ...
- AngularJS入门心得3——HTML的左右手指令
在<AngularJS入门心得1——directive和controller如何通信>我们提到“AngularJS是为了克服HTML在构建应用上的不足而设计的.HTML是一门很好的为静态文 ...
- AngularJS入门心得2——何为双向数据绑定
前言:谁说Test工作比较轻松,最近在熟悉几个case,差点没疯.最近又是断断续续的看我的AngularJS,总觉得自己还是没有入门,可能是自己欠前端的东西太多了,看不了几行代码就有几个常用函数不熟悉 ...
- AngularJS入门心得1——directive和controller如何通信
粗略地翻了一遍<JavaScript DOM编程艺术>,就以为可以接过AngularJS的一招半式,一个星期过去了,我发现自己还是Too Young,Too Simple!(刚打照面的时候 ...
- (一)Angularjs - 入门
AngularJS进行应用开发的一个重要的思维模式: 从构造声明式界面入手 ng-app: 这个指定定义并且关联了使用angularJS的HTML页面部分 ng-model: 这个指定定义并绑定Ang ...
- AngularJS入门教程:日期格式化
AngularJS入门教程:日期格式化[转载] 本地化日期格式化: ({{ today | date:'medium' }})Nov 24, 2015 2:19:24 PM ({{ today | d ...
- 【转载】图灵AngularJS入门教程
摘自图灵的AngularJS入门教程:http://www.ituring.com.cn/article/13471 感觉非常不错,所以推荐到首页一下! (一)Hello World! 开始学习Ang ...
- 《AngularJS入门与进阶》图书简介
一.图书封面 二.图书CIP信息 图书在版编目(CIP)数据 AngularJS入门与进阶 / 江荣波著. – 北京 : 清华大学出版社, 2017 ISBN 978-7-302-46074-9 Ⅰ. ...
- 跟我学AngularJs:AngularJs入门及第一个实例
林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka 摘要:主要给大家介绍了AngularJs及其特性,并以3个实例来做说明. 本教程使用Angul ...
随机推荐
- HTML5/CSS3基础
1. HTML 1.1 什么是HTML HTML是用来制作网页的标记语言 HTML是Hypertext Markup Language的英文缩写,即超文本标记语言 HTML语言是一种标记语言,不需要编 ...
- 2018.09.09 bzoj4403: 序列统计(Lucas定理)
传送门 感觉单调不降序列什么的不好做啊. 于是我们序列中下标为i的元素的值加上i,这样就构成了一个单调递增的序列. 问题就变成了: 求出构造长度分别为1 ~ n且每个元素的值在l+1 ~ r+n之间的 ...
- javascript 字符数组转换成以逗号隔开的字符串
var ids = [];angular.forEach(pulsarServers,function (server) { ids.push(server.id);});ids = ids.join ...
- ExtJS+SpringMVC文件上传与下载
说到文件上传.下载功能,网络上大多介绍的是采用JSP.SpringMVC或者Struts等开源框架的功能,通过配置达到文件上传.下载的目地.可是最近项目要用到文件上传与下载的功能,因为本项目框架采用开 ...
- (并查集)Travel -- hdu -- 5441(2015 ACM/ICPC Asia Regional Changchun Online )
http://acm.hdu.edu.cn/showproblem.php?pid=5441 Travel Time Limit: 1500/1000 MS (Java/Others) Memo ...
- RepositionBars的用法和参数的意义(引用别人的)
MFC窗口位置管理详细分析及实例 在一般用MFC编写的程序的窗口客户区中,可能有好几个子窗口(具有WM_CHILD风格的窗口).上边是工具栏,中间是视图窗口,下边是状态栏.三个窗 口在框架的客户区里和 ...
- HDU1459 非常可乐(BFS) 2016-07-24 15:00 165人阅读 评论(0) 收藏
非常可乐 Problem Description 大家一定觉的运动以后喝可乐是一件很惬意的事情,但是seeyou却不这么认为.因为每次当seeyou买了可乐以后,阿牛就要求和seeyou一起分享这一瓶 ...
- hbase使用MapReduce操作4(实现将 HDFS 中的数据写入到 HBase 表中)
实现将 HDFS 中的数据写入到 HBase 表中 Runner类 package com.yjsj.hbase_mr2; import com.yjsj.hbase_mr2.ReadFruitFro ...
- hdu 4995 离线处理+模拟
http://acm.hdu.edu.cn/showproblem.php?pid=4995 给定一维坐标下的n个点,以及每个点的权值,有m次查询,每次将查询的x点上的权值修改为离x最近的k个点权值的 ...
- 移动端与PC端的viewport
第一种解析: 设备像素,就是我们直觉上觉得"靠谱"的像素,这些像素为所使用的各种设备提供了正规的分辨率,并且其值可以通过(通常情况下)从screen.width/height属性中 ...