Angular4学习笔记(十)- 组件间通信

分类

  • 父子组件通信
  • 非父子组件通信

实现

代码如下:

message.service.ts

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

@Injectable()
export class MessageService {

  constructor() { }
  private subject = new Subject<any>();

  sendMessage(something: any) {
    this.subject.next(something);
  }

  clearMessage() {
    this.subject.next();
  }

  getMessage(): Observable<any> {
    return this.subject.asObservable();
  }
}

子组件

home.component.ts

import {Component, EventEmitter, OnInit, Output} from '@angular/core';
import {MessageService} from '../message.service';

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

  constructor(private messageService: MessageService) {
  }

  ngOnInit() {
  }

  sendMessage(): void { // 发送消息
    this.message = 'subject';
    this.messageService.sendMessage(this.message);
  }

  clearMessage(): void { // 清除消息
    this.messageService.clearMessage();
  }

}

home.component.html

<input type="button" value="Subject" (click)="sendMessage()">
<input type="button" value="clear" (click)="clearMessage()">

父组件
app.component.ts

import {Component, OnInit} from '@angular/core';
import {MessageService} from './message.service';
import {Subscription} from 'rxjs/Subscription';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit{
  message: any;
  subscription: Subscription;
  constructor(private messageService: MessageService) {
  }

  ngOnInit(): void {
    this.subscription = this.messageService.getMessage()
      .subscribe(message => { this.message = message; });
  }

  ngOnDestroy() {
    this.subscription.unsubscribe();
  }
}

app.component.html

<app-home></app-home>
<div>{{message | json}}</div>
  • 非父子

非父子组件见通信可以通过同一个service来实现。需要注意的是一定要在service中定义一个临时变量来供传递。比如我有两个组件来传递一个Book类型的数据,HomeComponent -> BookComponentBook和service定义如下:

import {EventEmitter, Injectable} from '@angular/core';
import {Subject} from 'rxjs/Subject';
export class Book {
  name: string;
  price: number;
}

@Injectable()
export class BookService {
  defaultBook: Book = {name: '《额尔古纳河右岸》', price: 20};
  bookEventer: EventEmitter<Book> = new EventEmitter();
}

主页组件HomeComponent,它用来提供数据源,定义如下:

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css'],
  encapsulation: ViewEncapsulation.None
})
export class HomeComponent implements OnInit, OnDestroy {
  book: Book;

  constructor(private bookService: BookService) {
  }

  ngOnInit() {
    this.book = {name: '《万历十五年》', price: 10.0};
  }

  ngOnDestroy() {
    this.bookService.bookEventer.emit(this.book);
  }
}

书籍组件BookComponent,用来接收数据,定义如下:

import {Component, OnInit, ViewEncapsulation} from '@angular/core';
import {Book, BookService} from './book';

@Component({
  selector: 'app-book',
  templateUrl: './book.component.html',
  styleUrls: ['./book.component.css'],
  encapsulation: ViewEncapsulation.None
})
export class BookComponent implements OnInit {
  protected subscribeBook: Book;

  constructor(private bookService: BookService) {
    bookService.bookEventer.subscribe(book => {
    bookService.defaultBook = book;
    });
  }

  ngOnInit() {
    this.subscribeBook = this.bookService.defaultBook;
  }
}

书籍组件模板文件定义如下:

<p>
  subscribeBook:{{subscribeBook | json}}
</p>

直接访问书籍模板对应路由的话,显示为:

先访问主页再访问书籍模板对应路由的话,显示为:

参考

RxJS - Subject
Angular 2 组件之间如何通信?
angular2.0+ 模块之间共享service并订阅更新

posted @ 2017-11-11 02:51  舒山  阅读(2882)  评论(0编辑  收藏  举报