掌握 Angular2 的服务 (service)

简介:

这篇文章我们来讲解如何使用service(服务),谈及服务我们就要了解什么是服务;在Angular中,我们所说的服务是指那些能够被其它的组件或者指令调用的单一的,可共享的代码块.服务能够使我们提高代码的利用率,方便组件之间共享数据和方法,方便测试和维护.

如果你看了上一篇文章Step 5 - Dependency Injection,你就会发现我们这一部分讲解的内容和上一篇有很多的相似之处;当然也有一些新的知识点,温故而知新嘛;好了让我们来开始今天的旅行吧.

首先我们还是切换回之前的quickstart版本,然后运行:


npm run start

可以看到My First Angular2 Travel,然后继续我们的铺垫工作;主要是三个部分:
1.将我们的组件模板使用单一的html模板来替代;
2.构建User类方便我们后面的使用;
3.构建我们的模拟数据,方便我们使用服务来获取这些数据;

首先我们来完成第一部分,修改app.component.ts@Component的元数据:template: '

My First Angular2 Travel

'改为:templateUrl: 'app/templates/main.html',然后我们在main.html中书写我们的模板代码:


My First Angular2 Travel

然后我们来进行第二个工作,创建我们的 User类;为了展示方便,我们就给 User两个属性吧,一个是 id(number),一个是 name(string);文件的路径是: app/classes/User.ts,具体的代码如下:
export class User {
    constructor(
        private id: number,
        private name: string
    ){}

上面注释的部分是这个User类的简写,这个根据个人的喜好;你喜欢写就怎么写.

最后一项工作就是来创造我们的模拟数据,我们现在还没有学习如何在Angular2中使用HTTP,所以我们暂时将这些数据记录在一个文件中,然后导出这些数据,供我们接下来使用.我们的模拟数据文件路径是:app/mock/user.data.ts;下面是代码部分:


import {User} from "../classes/User";
export const USERS: User[] = [
    {id: 1, name: 'dreamapple1'},
    {id: 2, name: 'dreamapple2'},
    {id: 3, name: 'dreamapple3'},
    {id: 4, name: 'dreamapple4'},
    {id: 5, name: 'dreamapple5'},
    {id: 6, name: 'dreamapple6'},
    {id: 7, name: 'dreamapple7'},
    {id: 8, name: 'dreamapple8'}

可以看到,我们导出了一个数组,这个数组的每一个元素都是一个User类的实例.

接下来,我们就要步入今天的主题了;构建一个服务,这个服务能够获取我们刚刚书写的模拟数据;首先不要忘记的是,service是一个类,然后这个类可以注入到别的组件
或者指令中去,还有一点就是我们知道,获取数据的服务往往都是异步的,所以我们使用了Promise去封装我们获取到的数据,来模拟异步请求;文件的路径是:app/service/user.service.ts,我们也遵循一个约定,服务的文件后缀是*.service.ts,前面的单词如果是多个的话就使用短横线来连接,比如SpecialUserService我们就写成special-user.service.ts,详细的部分请看代码:


import {User} from "../classes/User";
import {USERS} from "../mock/user.data";
export class UserService {
    getUsers(): User[] {
        return Promise.resolve(USERS);

关于上面代码的一些解释:因为我们的getUsers函数是有返回值的,它的返回值是一个数组,数组的每一个元素都是User类的实例,所以我们使用了getUsers(): User[],还有因为我们要模拟异步请求获取数据,所以我们使用了Promise,如果你对Promise有什么不懂的地方,可以看看这里.

接下来我们就要使用这个服务了,如何使用这个服务呢?在上一章节中我们已经讲解了许多种使用服务的方法;现在我们使用最简单的一种方式,直接使用providers来注入我们的服务,然后我们还要把我们获取到的数据展示到我们的模板中,具体的代码如下所示:


import {Component} from '@angular/core';
import {User} from "./classes/User";
import {UserService} from "./services/user.service";
 * 别忘记了使用@前缀
 * 这里相当于组件视图
 @Component({
    selector: 'my-app',
    templateUrl: 'app/templates/main.html',
    providers: [UserService]
 * 导出这个组件,也就是一个类
 * 这里相当于组件控制器
 export class AppComponent {
    users: User[];
    constructor(private userService: UserService){
        this.userService.getUsers().then(
            users => this.users = users

我们也要改动 main.html的内容:


My First Angular2 Travel


    
{{user.name}}

这时我们打开浏览器,就会看到我们想要的结果:

fe3c5784ed70d0610a0278b525fcafc017524df2

上面的写法是有一些问题的,构造函数是为了简单的初始化工作而设计的,比如把构造函数的参数赋值给属性.它的负担不应该过于沉重.所以我们把数据的获取放在了组件的生命周期的钩子函数中去,如果你不了解组件的生命周期的话,那么你可以看看这里,在这里我们使用了ngOnInit;我们修改一下上面的代码:

import {Component, OnInit} from '@angular/core';
import {User} from "./classes/User";
import {UserService} from "./services/user.service";
/*
 * 别忘记了使用@前缀
 * 这里相当于组件视图
 */
@Component({
    selector: 'my-app',
    //template: '

My First Angular2 Travel

',
    templateUrl: 'app/templates/main.html',
    providers: [UserService]
})
/*
 * 导出这个组件,也就是一个类
 * 这里相当于组件控制器
 */
export class AppComponent implements OnInit{
    users: User[];
    constructor(
        private userService: UserService
    ){}
    getUsersData() {
        this.userService.getUsers()
            .then(users => this.users = users);
    }
    ngOnInit() {
        this.getUsersData();
    }
}

上面代码的一些解释,首先我们在@angular/core中导出了OnInit这个接口,然后我们又通过组件中的ngOnInit方法实现了这个接口;将构造函数中的获取数据的业务提取了出来,这种做法是组件初始化的时候获取数据比较好的一种方案.我们在后面的文章中也会讲解关于组件或者指令生命周期的文章.

最后,我们还可以更真实的的去模拟从服务器读取数据的操作;我们可以通过使用setTimeout来延时获取我们的数据,这就很好地模拟了我们从服务器获取数据的操作;具体的代码部分看下面:


import {User} from "../classes/User";
import {USERS} from "../mock/user.data";
export class UserService {
    getUsers(): Promise {
        return Promise.resolve(USERS);
    getMockUsers(): Promise {
        return new Promise(resolve => setTimeout(resolve(USERS), 2000))
            .then(() => this.getUsers());

首先需要注意的一点是,我们之前写的代码把getUsers()函数的返回值定义为User[],其实更准确的应该是Promise[]>;我们接下来写的函数getMockUsers()利用setTimeout延时返回了我们的模拟数据.

其实我们的程序里还有一个小错误,不容易被发现;当我在构建的时候我发现了下面的错误:
services

它提醒我们说,Property 'id' is private in type 'User' but not in type '{ id: number; name: string; }'.这是因为我们把id作为User的私有属性了,但是在{ id: number; name: string; }对象中,id不是私有的属性;要解决这个问题有多种思路,你可以将我们的模拟数据使用User类来创建,或者将idname作为public属性.那我们就取一个简单的方法,将属性定义为public.User类的代码修改如下:


export class User {
    id: number;
    name: string;
    //constructor(
    //    private id: number,
    //    private name: string
    //){}
}


在TypeScript里,每个成员默认为是public的.所以上面的写法是很简便的.

到这里我们要说的内容已经说完了,源代码可以参考这里angular2-travel,当然欢迎批评指正.


原文发布时间为:2016年09月20日

原文作者:掘金

本文来源: 掘金 如需转载请联系原作者


相关文章
|
2月前
|
开发者 iOS开发 C#
Uno Platform 入门超详细指南:从零开始教你打造兼容 Web、Windows、iOS 和 Android 的跨平台应用,轻松掌握 XAML 与 C# 开发技巧,快速上手示例代码助你迈出第一步
【8月更文挑战第31天】Uno Platform 是一个基于 Microsoft .NET 的开源框架,支持使用 C# 和 XAML 构建跨平台应用,适用于 Web(WebAssembly)、Windows、Linux、macOS、iOS 和 Android。它允许开发者共享几乎全部的业务逻辑和 UI 代码,同时保持原生性能。选择 Uno Platform 可以统一开发体验,减少代码重复,降低开发成本。安装时需先配置好 Visual Studio 或 Visual Studio for Mac,并通过 NuGet 或官网下载工具包。
68 0
|
2月前
|
前端开发 UED 开发者
无障碍设计的魔法:JSF让每个用户都能畅游数字世界!
【8月更文挑战第31天】本文介绍如何使用JavaServer Faces (JSF)构建无障碍Web应用,确保所有用户都能访问和使用。文章通过实际代码示例展示了如何利用ARIA属性增强组件、实现键盘导航、提供文本替代以及使用语义化标签等技术。无障碍设计不仅是道德责任,也是提升用户体验的关键。通过这些方法,JSF可以帮助开发者创建更加公平和包容的应用。
27 0
|
3月前
|
设计模式 JavaScript 测试技术
Angular服务与依赖注入机制详解
【7月更文挑战第17天】Angular的服务与依赖注入机制为构建模块化、可维护和可扩展的应用程序提供了强大的支持。通过合理定义和使用服务,以及利用依赖注入来管理依赖关系,我们可以编写出更加清晰、可维护和可测试的代码。希望本文能帮助你更好地理解和应用Angular的服务与依赖注入机制。
|
3月前
|
前端开发 JavaScript
前端框架与库 - Angular基础:组件、模板、服务
【7月更文挑战第16天】Angular,谷歌维护的前端框架,专注构建动态Web应用。组件是核心,包含行为逻辑的类、定义视图的模板和样式。模板语法含插值、属性和事件绑定。服务提供业务逻辑,依赖注入实现共享。常见问题涉及组件通信、性能和服务注入。优化通信、性能并正确管理服务范围,能提升应用效率和质量。学习组件、模板和服务基础,打造高效Angular应用。
59 1
|
5月前
解决全网90%以上的日期格式转换、日期序列等骚操作问题
解决全网90%以上的日期格式转换、日期序列等骚操作问题
解决全网90%以上的日期格式转换、日期序列等骚操作问题
|
5月前
|
缓存 前端开发 JavaScript
Angular Service Worker 在 PWA 应用 HTTP 交互中扮演的角色
Angular Service Worker 在 PWA 应用 HTTP 交互中扮演的角色
|
Web App开发 缓存 安全
Angular 应用要启用 Service Worker 所需满足的一些前提条件
Angular 应用要启用 Service Worker 所需满足的一些前提条件
|
缓存 API
Angular 里的 Service Worker
从 5.0.0 版本开始,Angular 附带了一个 Service Worker 实现。 Angular 开发人员可以利用这个 service worker 并从其提供的更高的可靠性和性能中受益,而无需针对低级 API 编写代码。
|
存储 JavaScript API
如何使用 Angular 服务器端渲染的 Transfer State Service
如何使用 Angular 服务器端渲染的 Transfer State Service
|
资源调度 前端开发 Java
使用Angular CDK实现一个Service弹出Toast组件
使用Angular CDK实现一个Service弹出Toast组件
124 0

相关实验场景

更多