Angular基础知识学习(二)

hresh 508 0

Angular基础知识学习(二)

服务

创建服务之后,我们在 StorageService.service.ts 中定义一个测试方法:

export class StorageService {

  constructor() {

  }

  test() {
    alert('调用服务方法');
  }
}

我们重新建立一个 home 组件,来测试服务调用。

<p>home works!</p>

<button (click)="getService()">获取服务</button>
import { Component, OnInit } from '@angular/core';
import {StorageService} from '../../services/storage.service';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {

  constructor(public storage: StorageService) { }

  ngOnInit(): void {
  }

  getService() {
    this.storage.test();
  }

}

测试:

Angular基础知识学习(二)

数据持久化到localStroage

之前的 search 和 todoList 测试案例当页面刷新数据都会消失,接下来我们在 service 里构建数据持久化方法(实际是存放到浏览器的 localStroage 中)。

首先在 StorageService.service.ts 定义三个方法:

  set(key: string, value: string[]) {
    // @ts-ignore
    localStorage.setItem(key, JSON.stringify(value));
  }

  get(key: string) {
    return JSON.parse(localStorage.getItem(key));
  }

  remove(key: string) {
    localStorage.removeItem(key);
  }

在组件中调用服务里定义的方法:

import {Component, OnInit} from '@angular/core';
import {StorageService} from '../../services/storage.service';

@Component({
  selector: 'app-search',
  templateUrl: './search.component.html',
  styleUrls: ['./search.component.css']
})
export class SearchComponent implements OnInit {

  keyWord: any = '';

  keyWordsOld: any[] = [];

  product: any = '';
  products: any[] = [];

  constructor(public storage: StorageService) {
  }

  // 在初始化方法中查询localStorage中是否有数据
  ngOnInit(): void {
    // tslint:disable-next-line:prefer-const
    let serchList = this.storage.get('serchList');
    // tslint:disable-next-line:prefer-const
    let todoList = this.storage.get('todoList');
    if (serchList) {
      // @ts-ignore
      this.keyWordsOld = serchList;
    }
    if (todoList) {
      this.products = todoList;
    }
  }

  //输入内容后回车触发该方法
  keyup(e) {
    if (e.keyCode === 13){
      //首先判断搜索内容是否重复,若为新则加入
      if (this.keyWordsOld.indexOf(this.keyWord) === -1) {
        this.keyWordsOld.push(this.keyWord);

        this.storage.set('serchList', this.keyWordsOld);
      }
      this.keyWord = '';
    }
  }

  //搜索按钮绑定的方法
  search() {
    if (this.keyWordsOld.indexOf(this.keyWord) == -1) {
      this.keyWordsOld.push(this.keyWord);

      this.storage.set('serchList', this.keyWordsOld);
    }
    this.keyWord = '';
  }

  //删除按钮绑定的方法
  delete(key) {
    this.keyWordsOld.splice(key, 1);
    this.storage.set('serchList', this.keyWordsOld);
  }

  //回车事件,触发该方法
  add(e) {
    // tslint:disable-next-line:triple-equals
    if (e.keyCode == 13) {
      if (!this.equalProduct(this.products, this.product)) {
        this.products.push({
          title: this.product,
          status: 0
        });
        this.product = '';
        this.storage.set('todoList', this.products);
      } else {
        alert('数据已存在');
        this.product = '';
      }
    }
  }

  deleteWay(key) {
    this.products.splice(key, 1);
    this.storage.set('todoList', this.products);
  }

  //新增数据前与已有记录进行比对
  equalProduct(products: any[], value: any) {

    if (!value || value === '') {
      return false;
    }

    // tslint:disable-next-line:prefer-for-of
    for (let i = 0; i < products.length; i++) {
      // tslint:disable-next-line:triple-equals
      if (products[i].title == value) {
        return true;
      }
    }
    return false;
  }

  //change事件用来更新缓存中的内容
  change() {
    this.storage.set('todoList', this.products);
  }
}

html 文件基本不变,测试效果:

Angular基础知识学习(二)

注意观察下方 localStorage 中的内容,当页面刷新之后数据仍然存在。

生命周期

指令和组件的实例有一个生命周期:当 Angular 新建、更新和销毁它们时触发。 通过实现一个或多个 Angular core 库里定义的生命周期钩子接口,开发者可以介入该生命周期中的这些关键时刻。

每个接口都有唯一的一个钩子方法,它们的名字是由接口名再加上 ng 前缀构成的。比如,OnInit 接口的钩子方法叫做 ngOnInit, Angular 在创建组件后立刻调用它,:

export class PeekABoo implements OnInit {
  constructor(private logger: LoggerService) { }

  // implement OnInit's `ngOnInit` method
  ngOnInit() { this.logIt(`OnInit`); }

  logIt(msg: string) {
    this.logger.log(`#{nextId++}{msg}`);
  }
}

生命周期的顺序:

Angular基础知识学习(二)

这里我们重点学习 ngOnInit() 和 ngAfterViewInit()这两个方法。

首先新建 home 组件,其 html 内容为:

<h2>这里一个home组件---DOM操作演示</h2>

<div id="box">
  这是一个div标签
</div>
<br>
<div id="box2" *ngIf="flag" >
  这是第二个div标签
</div>

home.component.ts 文件内容为:

export class HomeComponent implements OnInit {

  flag = true;
  constructor() { }

  /*生命周期函数*/
  ngOnInit(): void {
    /*//组件和指令初始化完成,并不是真正的dom加载完成*/
    let oBox = document.getElementById('box');
    console.log(oBox.innerHTML);
    oBox.style.color = 'red';

    // 此处获取不到dom节点,所以最好不要在ngOnInit方法中获取dom节点
    /*let oBox2: any = document.getElementById('box2');
    console.log(oBox2.innerHTML);
    oBox2.style.color = 'blue';*/
  }

  // 视图加载完成后触发的方法,dom加载完成
  // tslint:disable-next-line: use-lifecycle-interface
  ngAfterViewInit(): void {
    let oBox2 = document.getElementById('box2');
    console.log(oBox2.innerHTML);
    oBox2.style.color = 'blue';
  }

}

通过操作 dom 节点来区分 ngOnInit 和 ngAfterViewInit 方法,前者用来初始化指令/组件,后者是当 Angular 初始化完组件视图及其子视图之后调用。所以后者才知道 box2 是否渲染完毕,然后才能获取到该 dom 节点并加以修改。

页面运行效果如下:

Angular基础知识学习(二)

父子组件之间通信传值

新建四个组件:news,home,header,footer。其中 home 和 header 是父子组件关系,news 和 footer 是父子组件关系 。

父组件通过@Input给子组件传值

1、home.component.html 用来传递变量和方法,也可以将 home 组件中所有信息传递过去。

<app-header [msg]="msg" [title]="title" [run]="run" [home]="this"></app-header>

<br>

<hr>

<br>

<h2>我是home组件</h2>

2、home.component.ts

export class HomeComponent implements OnInit {

  msg: any = '我是home组件的msg';
  title: any = 'home组件的title';

  constructor() { }

  ngOnInit(): void {
  }

  run() {
    return '执行home组件的run方法';
  }

}

3、header.component.html

<h2>我是header组件</h2>

<br>

<p>{{title}}-----{{msg}}</p>


<br>

<button (click)="getParentWay()">执行home组件的方法</button>

4、header.component.ts,子组件中需要引入 Input,用来接收父组件传过来的数据。

import { Component, OnInit, Input } from '@angular/core';

@Component({
  selector: 'app-header',
  templateUrl: './header.component.html',
  styleUrls: ['./header.component.css']
})
export class HeaderComponent implements OnInit {

  @Input() msg: any;

  @Input() title: any;

  @Input() run: any;
  /*//获取home组件所有内容*/
  @Input() home: any;

  constructor() { }

  ngOnInit(): void {
  }

  getParentWay() {
    // alert(this.run());
    alert(this.home.run());
  }

}

5、网页运行效果如下:

Angular基础知识学习(二)

6、小结

父组件给子组件传值,即子组件获取父组件的属性和方法,大致分为以下几步:

  1. 父组件页面嵌套子组件页面,将属性和方法存放在子组件声明中;
  2. 子组件引入 Input 模块;
  3. 子组件通过@Input 获取子组件声明中存放的属性和方法;

子组件通过ViewChild给父组件传值

1、news.component.html,

<app-footer #footerComponent></app-footer>

<br>
<hr>
<br>

<h2>我是news组件</h2>

<button (click)="getChildData()">获取子组件的数据</button>
<br>
<br>
<br>
<button (click)="getChildWay()">执行子组件的方法</button>

2、news.component.ts

import {Component, OnInit, ViewChild} from '@angular/core';

@Component({
  selector: 'app-news',
  templateUrl: './news.component.html',
  styleUrls: ['./news.component.css']
})
export class NewsComponent implements OnInit {

  @ViewChild('footerComponent') footer;

  constructor() {
  }

  ngOnInit(): void {
  }

  getChildData() {
    alert(this.footer.msg);
  }

  getChildWay() {
    this.footer.run();
  }

}

3、footer.component.html

<h2>我是footer组件</h2>

4、footer.component.ts

import {Component, OnInit} from '@angular/core';

@Component({
  selector: 'app-footer',
  templateUrl: './footer.component.html',
  styleUrls: ['./footer.component.css']
})
export class FooterComponent implements OnInit {

  msg: any = '我是footer组件的msg';

  constructor() {
  }

  ngOnInit(): void {
  }

  run() {
    alert('执行footer组件的run方法');
  }

}

5、网页运行效果如下:

Angular基础知识学习(二)

6、小结

子组件给父组件传值,即父组件主动获取子组件的属性和方法,大致分为以下几步:

  1. 父组件页面嵌套子组件页面,子组件声明时需要定义一个名称来代指子组件;
  2. 父组件引入 ViewChild 模块;
  3. 父组件通过@ViewChild 获取子组件的全部内容;

子组件通过Output给父组件传值

1、news.component.html,

<app-footer (outter)="run($event)"></app-footer>

<br>
<hr>
<br>

<h2>我是news组件</h2>

2、news.component.ts

import {Component, OnInit} from '@angular/core';

@Component({
  selector: 'app-news',
  templateUrl: './news.component.html',
  styleUrls: ['./news.component.css']
})
export class NewsComponent implements OnInit {

  constructor() {
  }

  ngOnInit(): void {
  }

  run(e) {
    console.log(e);
    alert('我是news组件的方法');
  }

}

3、footer.component.html

<h2>我是footer组件</h2>

<br>

<button (click)="sendMsg()">子组件广播事务</button>

4、footer.component.ts

import {Component, OnInit, Output, EventEmitter} from '@angular/core';

@Component({
  selector: 'app-footer',
  templateUrl: './footer.component.html',
  styleUrls: ['./footer.component.css']
})
export class FooterComponent implements OnInit {

  @Output() private outter = new EventEmitter();

  constructor() {
  }

  ngOnInit(): void {
  }

  sendMsg() {
    this.outter.emit('我是footer组件的数据');
  }
}

5、网页运行效果如下:

Angular基础知识学习(二)

6、小结

子组件给父组件传值,即父组件接收子组件的属性,大致分为以下几步:

  1. 子组件引入 Output、EventEmitter 模块;
  2. 子组件将要传输的数据封装在 outter 中;
  3. 父组件页面嵌套子组件页面,子组件声明时需要将 outter 指向父组件中的某个方法,注意接收数据;

父子组件相互通信

子组件 sizer.component.ts:

import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'app-sizer',
  templateUrl: './sizer.component.html',
  styleUrls: ['./sizer.component.css']
})
export class SizerComponent implements OnInit {

  @Input() size: number | string;
  @Output() sizeChange = new EventEmitter<number>();

  constructor() { }

  ngOnInit(): void {
  }

  inc() {
    this.resize(+1);
  }

  dec() {
    this.resize(-1);
  }

  resize(delta: number) {
    this.size = Math.min(40, Math.max(8, +this.size + delta));
    this.sizeChange.emit(this.size);
  }
}

sizer.component.html:

<h2>子组件</h2>
<div>
  <button (click)="dec()" title="smaller">-</button>&nbsp;&nbsp;
  <button (click)="inc()" title="bigger">+</button>
  <br>
  <br>
  <label [style.font-size.px]="size">FontSize: {{size}}px</label>
</div>

size 的初始值来自属性绑定的输入值。单击按钮可在最小值/最大值范围内增大或减小 size,然后带上调整后的大小发出 sizeChange 事件。

Home2Component.fontSize 首先传递给 SizerComponent$event 变量包含了 SizerComponent.sizeChange 事件的荷载。 当用户点击按钮时,Angular 将 $event 赋值给 Home2Component.fontSizePx。 父组件 home2.component.html:

<app-sizer [size]="fontSizePx" (sizeChange)="fontSizePx=$event"></app-sizer>

<h2>父组件</h2>
<div [style.font-size.px]="fontSizePx">Resizable Text</div>

Home2Component.fontSizePx 建立初始 SizerComponent.size 值。 home2.component.ts:

fontSizePx = 16;

页面测试:

Angular基础知识学习(二)

上述父子组件之间通信的关键在于:

<app-sizer [size]="fontSizePx" (sizeChange)="fontSizePx=$event"></app-sizer>

此处还可以通过双向绑定来实现, 双向绑定语法实际上是属性绑定和事件绑定的语法糖,所以还可以改为:

<app-sizer [(size)]="fontSizePx"></app-sizer>

Home2Component.fontSize 被双向绑定到 SizerComponent

Rxjs异步数据流编程

介绍

RxJS 是 ReactiveX 编程理念的 JavaScript 版本。ReactiveX 来自微软,它是一种针对异步数据
流的编程。简单来说,它将一切数据,包括 HTTP 请求,DOM 事件或者普通数据等包装成流
的形式,然后用强大丰富的操作符对流进行处理,使你能以同步编程的方式处理异步数据,
并组合不同的操作符来轻松优雅的实现你所需要的功能。

RxJS 是一种针对异步数据流编程工具,或者叫响应式扩展编程;可不管如何解释 RxJS 其目
标就是异步编程,Angular 引入 RxJS 为了就是让异步可控、更简单。

RxJS 里面提供了很多模块。这里我们主要给大家讲 RxJS 里面最常用的 Observable 和
fromEvent。

参考手册:https://www.npmjs.com/package/rxjs
中文手册:https://cn.rx.js.org/

关于异步编程方法的讲解,可以参考 Javascript异步编程的4种方法

目前常见的异步编程的几种方法:

  1. 回调函数
  2. 事件监听/发布订阅
  3. Promise
  4. Rxjs

本次测试需要新建一个 home2 组件,和 storage 服务,异步编程方法封装在 storage 服务中,供组件调用。

首先我们定义一个同步方法,来测试其效果。

1、storage.service.ts

  getData() {
    // console.log('this is service data');
    return 'this is service data';
  }

2、home2.component.ts

import {StorageService} from '../../services/storage.service';

  constructor(public storage: StorageService) {
  }

  /*//1、同步方法*/
  getData() {
    console.log(this.storage.getData());
  }

3、页面测试

Angular基础知识学习(二)

从结果可以看出,每点击一下按钮,同步方法就会立刻获取到数据。但是在实际生产中,同步操作容易造成堵塞问题,异步操作的出现很好的解决该问题。

回调函数

这是异步编程最基本的方法。

1、storage.service.ts

  // 一秒后获取数据
  getCallbackData(cb) {
    setTimeout(() => {
      // tslint:disable-next-line:prefer-const
      let username = 'hresh';
      cb(username);
    }, 1000);
  }

2、home2.component.ts

import {StorageService} from '../../services/storage.service';

  constructor(public storage: StorageService) {
  }

  getCallbackData() {
    /*2、通过Callback获取异步数据*/
    this.storage.getCallbackData((data) => {
      console.log(data);
    });//a操作
    console.log('延时获取数据');//b操作
  }

3、页面测试

Angular基础知识学习(二)

从页面结果来看,a操作不会阻塞程序运行,会被推迟执行,不会影响b操作的执行。

回调函数的优点是简单、容易理解和部署,缺点是不利于代码的阅读和维护,各个部分之间高度耦合(Coupling),流程会很混乱,而且每个任务只能指定一个回调函数。

事件监听

另一种思路是采用事件驱动模式。任务的执行不取决于代码的顺序,而取决于某个事件是否发生。

演示代码如下:

import { Component, OnInit } from '@angular/core';
import * as from 'jquery';

@Component({
  selector: 'app-home2',
  templateUrl: '
      <h2>事件监听</h2>
      <input type="button" value="点击" id="btn">
      <input type="button" value="移除" id="del">
    '
})
export class Home2Component implements OnInit {

  fn1() {
    alert('first');
  }

  fn1() {
    alert('first');
  }

  fn2() {
    alert('second');
  }

  ngOnInit(): void {('h2').css('color', 'blue');

    let body =('body');

    body.delegate('#btn', 'click', this.fn1);body.delegate('#btn', 'click', this.fn2);

    ('#del').on('done', () => alert('解除事件绑定'));

    setTimeout(() => {('#del').trigger('done');
    }, 2000);
  }

}

页面测试效果:

Angular基础知识学习(二)

#btn 标签可以绑定多个事件,$('#del').trigger('done')表示页面初始化后,2s 之后会触发 done 事件,从而执行 alert 事件。

这种方法的优点是比较容易理解,可以绑定多个事件,每个事件可以指定多个回调函数,而且可以"去耦合"(Decoupling),有利于实现模块化。缺点是整个程序都要变成事件驱动型,运行流程会变得很不清晰。

Promise

Promise 本意是承诺,在程序中的意思就是承诺我过一段时间后会给你一个结果。 什么时候会用到过一段时间?答案是异步操作,异步是指可能比较长时间才有结果的才做,例如网络请求、读取本地文件等。

它的思想是,每一个异步任务返回一个 Promise 对象,该对象有一个 then 方法,允许指定回调函数。比如,f1的回调函数f2,可以写成:

f1().then(f2);

在 Angular 项目中可以使用如下测试案例:

1、storage.service.ts

getPromiseData() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      // tslint:disable-next-line:prefer-const
      let username = 'hresh----Promise';
      resolve(username);
    }, 2000);
  });
}

2、home2.component.ts

import {StorageService} from '../../services/storage.service';

  constructor(public storage: StorageService) {
  }

  getPromiseData(){
    /*3、通过Promise获取异步数据*/
    let promiseObj = this.storage.getPromiseData();
    promiseObj.then((data) => {
      console.log(data);
    });
  }

3、页面测试

Angular基础知识学习(二)

另外 Promise 的 then 方法返回的是一个新的 Promise 实例,因此 then 可用链式调用。比如,指定多个回调函数:

f1().then(f2).then(f3);

再比如,指定发生错误时的回调函数:

f1().then(f2).fail(f3);

而且,它还有一个前面三种方法都没有的好处:如果一个任务已经完成,再添加回调函数,该回调函数会立即执行。所以,你不用担心是否错过了某个事件或信号。这种方法的缺点就是编写和理解,都相对比较难。

Rxjs

Rxjs 处理异步:

1、storage.service.ts

import { Observable } from 'rxjs';
getRxjsData() {
  return new Observable((observer) => {
    setTimeout(() => {
      let uname = 'hresh----Rxjs';
      observer.next(uname);
    }, 3000);
  });
}

2、home2.component.ts

import {StorageService} from '../../services/storage.service';

  constructor(public storage: StorageService) {
  }

  getRxjsData(){
    /*4、通过Rxjs获取异步数据*/
    let observer = this.storage.getRxjsData();
    let oData = observer.subscribe((data) => {
      console.log(data);
    });
  }

页面测试效果同 Promise 一样。从上面列子可以看到 RxJS 和 Promise 的基本用法非常类似, 除了一些关键词不同。 Promise 里面用的是 then() 和 resolve(),而 RxJS 里面用的是 next() 和 subscribe()。

其实Rxjs相比Promise 要强大很多。比如 Rxjs 中可以中途撤回、Rxjs 可以发射多个值、Rxjs 提供了多种工具函数等等。

Rxjs 可以通过 unsubscribe() 可以撤回 subscribe 的动作。

我们修改 home2.component.ts 文件内容如下:

import {StorageService} from '../../services/storage.service';

  constructor(public storage: StorageService) {
  }

  getRxjsData(){
    /*4、通过Rxjs获取异步数据*/
    let observer = this.storage.getRxjsData();
    let oData = observer.subscribe((data) => {
      console.log(data);
    });

      /*5、Rxjs允许取消订阅操作*/
    setTimeout(() => {
      oData.unsubscribe();
    }, 2000);
  }

数据交互(Get,Post,jsonp)

Angular5.x 以后 Get、Post 和 jsonp 通过 HttpClientModule 模块来和服务器进行数据交互。

Get获取数据

1、 在 app.module.ts 中引入 HttpClientModule

import {HttpClientModule} from '@angular/common/http';

imports: [
    BrowserModule,
    HttpClientModule,
    HttpClientJsonpModule
]

2、html 文件内容:

<p>new3 works!</p>

<br>
<hr>
<br>

<button (click)="getData()">get请求数据</button>

<br>
<hr>
<br>

<ul>
  <li *ngFor="let item of dataList">{{item.name}} --- {{item.age}}</li>
</ul>

<br>

3、new3.component.ts 文件

import {Component, OnInit} from '@angular/core';
import {HttpClient, HttpHeaders} from '@angular/common/http';

@Component({
  selector: 'app-new3',
  templateUrl: './new3.component.html',
  styleUrls: ['./new3.component.css']
})
export class New3Component implements OnInit {

  dataList: any[] = [];

  constructor(public client: HttpClient) {
  }

  ngOnInit(): void {
  }

  getData() {
    // var api = 'http://a.itying.com/api/productlist';
    var api = 'https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json';
    this.client.get(api).subscribe((data: any) => {
      console.log(data);
      this.dataList = data.members;
    });
  }
}

4、网页运行效果如下:

Angular基础知识学习(二)

Post获取数据

在 SpringMVC 项目构建后台服务方法,一个是用 RequestBody 接受参数,另一个是用 RequestParam 接受参数。

@RestController
@CrossOrigin(origins = "http://localhost:4200")
public class EncodingController {

    @RequestMapping(value = "/testPostPara2")
    public Map testPostPara2(@RequestParam String uname,@RequestParam int age){
        Map<String,Object> map = new HashMap<String, Object>();
        map.put("name",uname);
        map.put("age",age);
        return map;
    }

    @RequestMapping("/testPostBody")
    public Map testPostBody(@RequestBody Map<String,Object> objectMap){
        System.out.println(objectMap.toString());
        return objectMap;
    }
}

出于安全原因,浏览器禁止 Ajax 调用驻留在当前原点之外的资源。例如,当你在一个标签中检查你的银行账户时,你可以在另一个选项卡上拥有 EVILL 网站。来自 EVILL 的脚本不能够对你的银行 API 做出 Ajax 请求(从你的帐户中取出钱!)使用您的凭据。 跨源资源共享(CORS)是由大多数浏览器实现的W3C规范,允许您灵活地指定什么样的跨域请求被授权,而不是使用一些不太安全和不太强大的策略,如IFRAME或JSONP。关于跨域的更多内容可以参考注解@CrossOrigin解决跨域问题

注意上述方法都返回的是 Map 类型,不需要转换为 String 类型返回。但是如果直接访问 http://localhost:8080/testPostPara2?uname=hresh22&age=24 是会报错的,必须转换为 String 类型。

1、同样需要在 ap.module.ts 中引入 HttpClientModule 模块并注入。

2、html

<br>

<button (click)="doPost2()">post提交数据:body中传参</button>

<br>
<hr>
<br>
<button (click)="doPost()">post提交数据:url后携带参数</button>

3、new3.component.ts 文件

import {Component, OnInit} from '@angular/core';
import {HttpClient, HttpHeaders} from '@angular/common/http';

@Component({
  selector: 'app-new3',
  templateUrl: './new3.component.html',
  styleUrls: ['./new3.component.css']
})
export class New3Component implements OnInit {

  dataList: any[] = [];

  constructor(public client: HttpClient) {
  }

  ngOnInit(): void {
  }

  doPost() {
    const header = { headers: new HttpHeaders({ 'Content-Type': 'application/json' }) };
    let url = 'http://localhost:8080/testPostPara2?uname=hresh22&age=24';
    this.client.post(url, {}, header).subscribe((response: any) => {
      console.log(response);
    });
  }
  doPost2() {
    const header = { headers: new HttpHeaders({ 'Content-Type': 'application/json' }) };
    let url = 'http://localhost:8080/testPostBody';
    this.client.post(url, { 'uname': 'hresh', 'age': 24 }, header).subscribe((response: any) => {
      console.log(response);
    });
  }
}

4、页面测试

需要先启动 web 项目,然后再启动 Angular 项目,点击页面上的按钮,查看效果。

Angular基础知识学习(二)

jsonp获取数据

同 Get 请求获取数据一样,然后主要是添加 html 文件和 ts 中的方法。

1、 在 app.module.ts 中引入 HttpClientJsonpModule

import {HttpClientJsonpModule} from '@angular/common/http';

imports: [
    BrowserModule,
    HttpClientJsonpModule
]

2、html

<button (click)="getJsonpData()">Jsonp获取数据</button>

3、new3.component.ts 文件

  getJsonpData() {
    var api = 'http://a.itying.com/api/productlist';
    this.client.jsonp(api, 'callback').subscribe((data) => {
      console.log(data);
    })
  }

4、页面测试

Angular基础知识学习(二)

第三方模块axios获取数据

1、安装 axios

npm install axios 

2、配置服务文件 httpservice.service.ts

import {Injectable} from '@angular/core';
import axios from 'axios';
import {Observable} from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class HttpserviceService {

  constructor() {
  }

  //可以返回Promise对象,也可以使用Rxjs,根据个人习惯
  axiosGet(api) {
    return new Promise((resolve, reject) => {
      axios.get(api).then(function(res) {
        resolve(res);
      });
    });
  }

  axiosRxjs(api) {
    return new Observable(function(observer) {
      axios.get(api).then(function(res) {
        observer.next(res);
      });
    });
  }
}

3、html 文件

<button (click)="getAxiosData()">Axios获取数据方式一</button>
<hr>
<br>
<button (click)="getAxiosData2()">Axios获取数据方式二</button>

4、在用到的地方引入 httpservice 并在构造函数声明

import { HttpserviceService } from '../../services/httpservice.service';

  constructor(public client: HttpClient, public httpservice: HttpserviceService) {
  }

  //通过第三方模块获取服务器数据
  getAxiosData() {
    var api = 'http://a.itying.com/api/productlist';
    let axiosObj = this.httpservice.axiosGet(api);
    axiosObj.then((data) => {
      console.log(data);
    })
  }

  //通过Rxjs获取
  getAxiosData2() {
    var api = 'http://a.itying.com/api/productlist';
    let axiosObj = this.httpservice.axiosRxjs(api);
    axiosObj.subscribe(function (data) {
      console.log(data);
    })
  }

5、页面测试

Angular基础知识学习(二)

发表评论 取消回复
表情 图片 链接 代码

分享