A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 AreYouGlad 于 2018-1-12 19:11 编辑

查看更多精彩前端资源


服务
什么是服务
  • 在Angular中, 以组件为中心的进行开发, 如果组件中存在公共的逻辑处理, 那么可以抽取为一个服务(都是js逻辑, 没有模版与样式)
  • 所以服务就是一段复用性很强的逻辑代码,最常见的服务比如Http请求, Cookie操作, Storage操作, 数据格式转换, 排序处理等等

使用服务的好处
  • 与大部分的技术解决方案一样, 可以提高程序的复用性, 减少冗余代码, 提高可维护性, 增加代码质量等等
  • 如果说函数是代码复用的形式, 对象是比函数高一维度的复用形式, 那么Angular服务是比对象再高一维度的复用表现形式

文件组织
  • Angular一个服务一般由一个文件构成, 所以每个服务不用单独建立文件夹
  • 一般会在项目中建立一个专门用来存放服务的文件夹, 与Angular的其他功能文件进行区分
  • 如果服务比较多, 那么可以再建立文件夹, 对服务的种类进行进一步划分

创建服务
  • cli工具提供了自动创建各种angular文件的命令, 用于快速生成文件

创建文件
  • 约定: 在app目录下创建一个service目录作为所有服务的根目录
  • 运行命令创建storage服务: ng g service service/storage

编码实现
  • 因为localStorage在前端应用比较多, 所以我们尝试封装一下它, 让它变得更好用
  • localStorage在存取值的时候必须为字符串,而我们大部分情况下存储的都是复杂数据类型
  • 所以在使用时通常要进行数据格式转换, 转换时可能还要进行错误处理,我们就把这个过程进行封装

[JavaScript] 纯文本查看 复制代码
import { Injectable } from '@angular/core';

@Injectable()
export class StorageService {

        // 封装setItem
  set(key: string, data: any): void {
          // 先尝试把val序列化为字符串
          // 如果成功了就存储成功的值, 否则原物存储
    try {
      data = JSON.stringify(data);
    }finally {
      localStorage.setItem(key, data);
    }
  }

        // 封装getItem
  get(key: string): any {
          // 先从本地取出字符串值, 然后尝试解析为js对象
          // 如果成功了就返回成功的值, 否则原物返回
    let data = localStorage.getItem(key);
    try {
      data = JSON.parse(data);
    }finally {
      return data;
    }
  }

        // 封装removeItem
  remove(key: string): void {
    localStorage.removeItem(key);
  }

        // 封装clear
  clear(key: string): void {
    localStorage.clear();
  }
}

注册服务
  • 使用Angular服务与组件一样需要先进行注册, 因为cli工具没有自动注册, 所以需要我们自己来
  • 打开app.module.ts文件, 导入刚刚创建的服务, 然后配置到providers里面

[JavaScript] 纯文本查看 复制代码
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';

// 导入服务, 注意导入的名称别写错
import { StorageService } from './service/storage.service';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule
  ],
  providers: [
    StorageService   // 服务在这里进行配置
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

使用服务
  • 注册好的组件在html中通过标签使用, 而服务是在ts中使用的, 大概有如下两步
  • 第一步: 打开需要使用服务的组件app.component.ts, 然后导入StorageService
  • 第二步: 在构造器中使用简写方式定义一个属性, 类型为StorageService
  • 这样写Angular会自动帮我们创建StorageService实例并赋值给storage属性
[JavaScript] 纯文本查看 复制代码
import { Component } from '@angular/core';
import { StorageService } from './service/storage.service';  // 导入服务

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {

        // 给实例添加storage属性, 类型为StorageService,
        // 然后Angular会自动帮我们创建StorageService实例并赋值给storage属性
        constructor(public storage: StorageService) {
                console.log(this.storage);      // 打印的是实例
                this.storage.set('test', 123);    // 使用测试
        }
}

依赖注入
  • 在Angular中使用服务, 不建议我们手动实例化服务
  • 而是在构造器上声明所需的服务类型, 然后由Angular自动进行实例化并传入赋值
  • 这是Angular采用的一种程序设计模式, 称为依赖注入

依赖注入好处
  • Angular中全局注册的服务是单例的, 就是说Angular会缓存第一次创建的服务实例
  • 然后让我们在多个地方使用, 这样可以节省内存与实例化过程的开销, 还可以在必要时共享数据

使用不用管依赖注入吗
  • 如果你的项目规模不大, 也不需共享数据, 不需缓存实例, 不需其他更高级的好处, 那么完全可以!
  • 当然也有一些人认为Angular里的很多东西有点设计过度了, 如果不想使用依赖注入, 那么是无需在根模块进行注册的
  • 我们要做的就是: 定义服务类, 然后在需要的地方导入并使用
  • 注意: 对于Angular内置的服务, 我们还是得使用依赖注入的方式

HTTP
  • 在Angular4的时候官方提供了单独的@angular/http模块
  • 不过刚刚发布的Angular5官方推荐更简单易用的替代产品@angular/common/http模块

配置
  • 要使用http模块的东西, 必须先进行配置
  • 打开app.module.ts文件, 导入HttpClientModule模块, 然后配置到providers里面

[JavaScript] 纯文本查看 复制代码
import { HttpClientModule } from '@angular/common/http';

@NgModule({
  imports: [
    HttpClientModule
  ]
})
export class AppModule { }

使用范例
  • 打开app.component.ts文件, 导入发送客户端请求的HttpClient
  • 然后在构造器中使用简写方式定义一个http属性, 类型为HttpClient

    • 这样写Angular会自动帮我们创建HttpClient实例并赋值给http属性


[JavaScript] 纯文本查看 复制代码
import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';  // 导入HttpClient类

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
        // 定义http属性, Angular会自动创建HttpClient实例
        constructor(private http: HttpClient) {
                  console.log(this.http);  // 打印测试一下
          }
}

get请求
  • angular使用了rxjs库进行异步编程中的数据处理, 所以调用http相关方法会得到一个Observable实例(观察者模式类)
  • 然后调用toPromise方法就可以转成我们熟悉的Promise实例, 通过thencatch添加成功失败回调
  • 补充: 如果不转成Promise实例, 我们也可以直接Observable实例的subscribe方法添加成功与失败回调

[JavaScript] 纯文本查看 复制代码
import { HttpClient } from '@angular/common/http';

export class AppComponent {
        constructor(private http: HttpClient) {

                // 调用get方法发送请求, 然后调用toPromise方法转成Promise实例
            // 接下来就按照Promise的API添加成功或失败处理函数
            this.http.get('http://vue.studyit.io/api/getprodlist').toPromise()
            .then(
              (data) => console.log(data),
              (err) => console.log(err)
            );

            // 或者直接调用subscribe方法
            this.http.get('http://vue.studyit.io/api/getprodlist')
            .subscribe(
              (data) => console.log(data),
              (err) => console.log(err)
            );

          }
}

post请求
  • post请求发送的数据一般会分为两种数据格式
  • 如果是json数据格式的话比较方便, 直接调用传个对象即可
  • 如果是formData数据格式的话比较麻烦, 需要导入HttpHeaders然后设置请求头, 还需要自己转换数据格式

[JavaScript] 纯文本查看 复制代码
import { HttpClient, HttpHeaders } from '@angular/common/http';

export class AppComponent {
        constructor(private http: HttpClient) {

                // post请求, 发送json格式数据
            // 注意!: 我们演示的这个接口不支持json数据格式, 所以会添加失败, 大家把这个请求方式记下来以备后患
            this.http.post('http://vue.studyit.io/api/addproduct', {name: '飞机'}).toPromise()
            .then(
              (data) => console.log(data),
              (err) => console.log(err)
            );

                // post请求, 发送formData格式数据
            // 我们的接口需要的就是formData数据格式, 所以这里可以添加成功
            // 注意!: 这里使用的HttpHeaders需要在上面引入后才能使用
            const postFormDataConfig = { headers: new HttpHeaders({'Content-Type': 'application/x-www-form-urlencoded'}) };
            this.http.post('http://vue.studyit.io/api/addproduct', 'name=火车', postFormDataConfig).toPromise()
            .then(
              (data) => console.log(data),
              (err) => console.log(err)
            );

          }
}

1 个回复

正序浏览
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马