在这一步中,我们将会改变我们获取数据的方式。

  ·我们定义一个代表RESTful客户端的自定义服务。使用这个客户端,我们可以用一种更简单的方法向服务端请求数据,而不用处理更底层的$httpAPI,HTTP方法和URLs。

最重要的变化列举如下,您可以点击这里在GitHub上查看全部的不同。

依赖

RESTful功能由Angular的ngResource模块提供,这是从Angular核心模块中独立出来的。

由于我们使用了Bower来安装客户端的依赖,这一步更新bower.json配置文件来添加新的依赖:

bower.json:

{
"name": "angular-phonecat",
"description": "A starter project for AngularJS",
"version": "0.0.0",
"homepage": "https://github.com/angular/angular-phonecat",
"license": "MIT",
"private": true,
"dependencies": {
"angular": "1.5.x",
"angular-mocks": "1.5.x",
"angular-resource": "1.5.x",
"angular-route": "1.5.x",
"bootstrap": "3.3.x"
}
}

新的依赖"angular-resource": "1.5.x"告诉bower安装一个与Angular1.5.x版本兼容的angular-resource模块。我们必须告诉bower来下载和安装该依赖。

npm install

服务

我们在服务端创建我们自己的服务来提供获取数据的入口。我们将服务置于其自己的模块,在core下,以便我们能直接在ngResource中声明其依赖:

app/core/phone/phone.module.js:

angular.module('core.phone', ['ngResource']);

app/core/phone/phone.service.js:

angular.
module('core.phone').
factory('Phone', ['$resource',
function($resource) {
return $resource('phones/:phoneId.json', {}, {
query: {
method: 'GET',
params: {phoneId: 'phones'},
isArray: true
}
});
}
]);

我们使用模块API来注册一个自定义服务,这使用了一个工厂函数。我们将其在服务的名字--“Phone”--和工厂函数中传递。工厂函数和构造函数很相似,在于两者都能通过函数参数声明将被注入的依赖。Phone服务在$resource服务中声明了一个依赖,这是由ngResource模块提供的。

$resource服务使得创建一个RESTful客户端变得很容易,仅仅几行代码即可。该客户端就能在我们的应用中被使用了,以此来代替更底层的$http服务。

app/core/core.module.js:

angular.module('core', ['core.phone']);

我们需要在core模块中将core.phone模块添加为一个依赖。

模板

我们自定义的服务会在app/core/phone/phone.service.js中被定义,所以我们将该文件连同.module.js文件一起包含进我们的布局模板。另外,我们也需要加载angular-resource.js文件,这包含了ngResource模板:

app/index.html:

<head>
...
<script src="bower_components/angular-resource/angular-resource.js"></script>
...
<script src="core/phone/phone.module.js"></script>
<script src="core/phone/phone.service.js"></script>
...
</head>

组件控制器

现在我们可以通过提取出更底层的$http服务来简化我们的组件控制器(PhoneListController 和 PhoneDetailController),将其替换为新的Phone服务。Angular的$resource作为RESTful资源,相较于$http更易用于与数据源打交道。现在也更好理解我们控制器中的代码在做什么了。

app/phone-list/phone-list.module.js:

angular.module('phoneList', ['core.phone']);

app/phone-list/phone-list.component.js:

angular.
module('phoneList').
component('phoneList', {
templateUrl: 'phone-list/phone-list.template.html',
controller: ['Phone',
function PhoneListController(Phone) {
this.phones = Phone.query();
this.orderProp = 'age';
}
]
});

app/phone-detail/phone-detail.module.js:

angular.module('phoneDetail', ['core.phone']);

app/phone-detail/phone-detail.component.js:

angular.
module('phoneDetail').
component('phoneDetail', {
templateUrl: 'phone-detail/phone-detail.template.html',
controller: ['$routeParams', 'Phone',
function PhoneDetailController($routeParams, Phone) {
var self = this;
self.phone = Phone.get({phoneId: $routeParams.phoneId}, function(phone) {
self.setImage(phone.images[0]);
}); self.setImage = function setImage(imageUrl) {
self.mainImageUrl = imageUrl;
};
}
]
});

注意到在PhoneListController中我们如何替换:

$http.get('phones/phones.json').then(function(response) {
self.phones = response.data;
});

为:  

this.phones = Phone.query();

这是一句简单且声明式的语句来说明我们想要查询所有的电话。

值得一提的是在上面的代码中,当调用Phone服务中的方法时候,我们没有传递任何回调函数。虽然看上去结果是同步返回了,结果完全不是这样。同步返回的是一个“future”--一个当XHR响应收到时,会被填满数据的对象。由于Angular数据绑定的存在,我们可以将这个future绑定到我们的模板。这样的话,当数据到达时,视图会被自动更新。

有时候,仅仅依赖future对象和数据绑定不能满足我们想做的任何事,在这些情况下,我们可以添加一个回调来运行服务器响应。phoneDetail组件控制器通过在回调中设置mainImageUrl来实现。

总结

既然我们已经知道如何构建一个自定义服务,使其成为一个RESTful客户端,让我们进入下一步来学习如何通过动画来提高用户体验。

[Angular Tutorial] 13 -REST and Custom Services的更多相关文章

  1. [Angular Tutorial]PhoneCat Tutorial App

    (注:曾经在<不敢止步>一书中看到学到一个观点,作者认为学习一门技术最好的方法就是翻译某部领域书籍.这里我决定做一次尝试,接下来花1个月左右时间,将Angular Tutorial Pho ...

  2. [Angular Tutorial] 11 -Custom Filters

    在这一步中您将学到如何创建您自己的展示过滤器. ·在先前的步骤中,细节页面展示“true”或“false”来显示某部电话是否有某项功能.在这一步中,我们将使用自定义的过滤器来将这些个字符串转化成符号: ...

  3. [Angular Tutorial] 3-Components

    在先前的步骤中,我们看到了一个控制器和一个模板如何一起工作来将一个静态的HTML文件转化为动态页面(view).一般说来,这在单页应用中一种非常常见的模式(在Angular应用中尤其是这样): ·客户 ...

  4. [Angular Tutorial] 7-XHRs & Dependency Injection

    我们受够了在应用中用硬编码的方法嵌入三部电话!现在让我们用Angular内建的叫做$http的服务来从我们的服务器获取更大的数据集吧.我们将会使用Angular的依赖注入来为PhoneListCtrl ...

  5. [Angular Tutorial] 0-Bootstraping

    在这一节的tutorial中,您将会逐渐熟悉AngularJS phonecat app的最重要的源代码文件.您也将学到如何将开发服务器与angular-seed绑定到一起,并且在浏览器中运行应用. ...

  6. [Angular2 Form] Angular 2 Template Driven Form Custom Validator

    In this tutorial we are going to learn how we can also implement custom form field validation in Ang ...

  7. AngularJS学习---REST和自定义服务(REST and Custom Services) ngResource step 11

    1.切换目录 git checkout step- npm start 2.效果图 效果图和step 10的没有什么差别,这里主要的改动都是代码,代码做了很多优化,这里效果图就不再贴出来了. 3.实现 ...

  8. Part 13 Create a custom filter in AngularJS

    Custom filter in AngularJS 1. Is a function that returns a function 2. Use the filter function to cr ...

  9. [Angular Tutorial] 14 -Animations

    在这一步中,我们将会通过在我们先前创建的模板代码中添加CSS和JavaScript动画效果来扩展我们的web应用. ·我们现在使用ngAnimate模块来允许动画效果贯穿整个应用. ·我们也依赖于自带 ...

随机推荐

  1. UVA 10200 Prime Time (打表)

    题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem ...

  2. JSP标准标签库(JSTL)--国际化标签库 fmt

    JSTL中使用fmt.tld作为格式化标签库的定义文件 No. 功能分类 标签名称 描述 1 国际化标签 <fmt:setLocale> 设置一个全局的地区代码 2 <fmt:req ...

  3. CF 672 div2 D

    http://codeforces.com/contest/672/problem/D 题目大意: 有n个人,每个人有pi的钱,然后可以由如下操作,每次都可以挑选一个最富有的人,把它的钱给最穷的人.但 ...

  4. css 内联与块

    内联元素可以理解为不能直接设置宽度和高度元素,比如span,你为他设置宽度和高度没有效果,除非你把它设置成块级元素. 如下面的代码把display:block;属性值去掉的话,宽度和高度都不会起作用了 ...

  5. hrbustoj 1494(原题UVA 315 Network) 解题报告 tarjan求割点

    主要思路:使用tarjan选取一个根节点建立一个棵搜索树,判断一个点是割点的充分必要条件是,对于一个节点u如果他的孩子节点v的low值大于等于u的出生日期dfn值,进行下一步判断,如果u是我们选的根节 ...

  6. codeforces 665C Simple Strings

    相同的一段字母变一下就可以. #include<cstdio> #include<cstring> #include<cmath> #include<vect ...

  7. Html基础详解

    HTML是(Hyper Text Mark-up Language)超文本标记语言,是因特网上应用最为广泛的一种网络传输协议,所有的www文件都必须要遵守这个标准.这样就可以让浏览器根据标记语言的规则 ...

  8. RS485通讯协议的应用 (转)

    源:http://blog.chinaunix.net/uid-26921272-id-3506640.html RS485缺点: RS485总线是一种常规的通信总线,它不能够做总线的自动仲裁,也就是 ...

  9. 【HighCharts系列教程】四、颜色属性——colors

    一.Colors属性说明 配置Colors,可以自定义数据列的颜色. 默认下colors就包含一系列颜色,在个性化或需要调整颜色的顺序下,我们可以配置该属性. 二.colors属性详解 Colors属 ...

  10. 添加<!doctype html>后造成JS写的定位失效

    今天同事找了一个悬浮广告的插件,但是一放入页面中就失效了,也没有报错,后来通过原文件对比,发现是加了<!doctype html>. 这样子定位并不起效果: document.getEle ...