首页 文章

Angular2 / 4取消订阅在一个永不被破坏的组件中可观察到

提问于
浏览
0

我是Angular4的新手 . 很抱歉基本问题和我可怜的英语 . 我会尽力描述我的问题 .

我现在正在开发一个使用可观察服务来共享消息的网站 .

但我遇到了问题,这是我的example file structure . 和working Plunker .

我从“用户组件”收到了“标头组件”消息 .

Headers 组件:

import { Component, OnInit, OnDestroy} from '@angular/core';
import { Subscription } from 'rxjs/subscription';
import { SharedService } from "./sharedService";

@Component({
  selector: 'shared-header',
  template: `<div class="my-header">
              <span>This is header </span>
              <span class="right-align">Recieve Data:{{received}}</span>  
            </div>`,
})

export class HeaderComponent implements OnInit, OnDestroy{

  private subscription: Subscription;
  private received = "none";

  constructor(private sharedService : SharedService) {}

  ngOnInit(){
    this.subscription = this.sharedService.shareAction$.subscribe(result => {
      if(result){
        this.received = result;
      } 
    };
  }

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

用户组件:

import { Component, OnInit, OnDestroy} from '@angular/core';
import { Subscription } from 'rxjs/subscription';
import { SharedService } from "./sharedService";

@Component({
  selector: 'shared-header',
  template: `<div class="my-header">
              <span>This is header </span>
              <span class="right-align">Recieve Data:{{received}}</span>  
            </div>`,
})

export class HeaderComponent implements OnInit, OnDestroy{

  private subscription: Subscription;
  private received = "none";

  constructor(private sharedService : SharedService) {}

  ngOnInit(){
    this.subscription = this.sharedService.shareAction$.subscribe(result => {
      if(result){
        this.received = result;
      } 
    };
  }

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

和“Widget组件”从“产品组件”收到消息 .

小部件组件:

import { Component, OnInit, OnDestroy} from '@angular/core';
import { Subscription } from 'rxjs/subscription';
import { SharedService } from "./sharedService";

@Component({
  selector: 'widget',
  template: `<div>---Widget----</div>
             <div>=={{productName}}==</div>`,
})

export class WidgetComponent implements OnInit, OnDestroy{

  private productName = "none";
  private subscription: Subscription;

  constructor(private sharedService : SharedService) {}

  ngOnInit(){
    this.subscription = this.sharedService.shareAction$.subscribe(result => {
      if(result){
        this.productName = result;
      } 
    };
  }
  ngOnDestory(){
    this.subscription.unsubscribe();
  }
}

产品组件:

import { Component, OnInit, OnDestroy} from '@angular/core';
import { SharedService } from "./sharedService";

@Component({
  template: `<h4>This is ProductPage</h4>
             <widget></widget>`,
})

export class ProductComponent implements OnInit, OnDestroy{

  constructor(private sharedService : SharedService) {}

  ngOnInit(){
    this.sharedService.publishData('NIKE');
  }
}

我创建了一个sharedService来处理可观察的服务 . 共享服务:

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Subscription } from 'rxjs/subscription';

@Injectable()
export class SharedService {

  private shareAction = new BehaviorSubject<any>(null);
  shareAction$ = this.shareAction.asObservable()
  sharedObject: object = {};

  constructor() {}

  publishData(data) {
    console.log('publish------------------------------');
    this.shareAction.next(data);
  }
}

因此,当点击“用户页面”时, Headers 右侧的信息将显示“用户页面” . 点击“产品页面”时,小部件下方的信息将显示“NIKE” . 但同时, Headers 信息也变为“NIKE”,我不希望它发生 .

我知道我应该在组件销毁时取消订阅,但在这种情况下,Header永远不会被销毁 . 所以也许....我应该在“用户组件”销毁时取消订阅,并在“用户组件”初始化时再次订阅,但我不知道该怎么做,或者这个想法很糟糕 .

请给我一些指导,任何意见都会有所帮助 . 非常感谢 .

2 回答

  • 0

    我认为问题是你使用单个 shareAction$ 来做太多事情 . 为什么不为 Headers 信息创建一个主题,为小部件创建另一个主题?

    此外, shareAction$ 过于宽泛:尝试给它一个更具体的名称,如 headerTitle$currentProduct$

    import { Injectable } from '@angular/core';
    import { BehaviorSubject } from 'rxjs/BehaviorSubject';
    import { Subscription } from 'rxjs/subscription';
    
    @Injectable()
    export class SharedService {
    
        private headerTitle = new BehaviorSubject<string>(null);
        headerTitle$ = this.headerTitle.asObservable();
    
        private currentProduct = new BehaviorSubject<any>(null);
        currentProduct$ = this.currentProduct.asObservable();
    
        constructor() {}
    
        setHeaderTitle(title:string):void {
            this.headerTitle.next(title);
        }
        setCurrentProduct(product:any):void {
            this.currentProduct.next(product);
        }
    }
    

    这样,Header组件和Widget组件都不需要知道何时订阅/取消订阅:它们只是在创建时订阅并在销毁时取消订阅 .

    另外,考虑避免使用 any 作为类型:当你的应用程序足够大时,它会为你节省很多问题,因为如果有错误的话 .

    您是否需要通过服务全局共享 CurrentProduct ?如果你只在Product组件中使用它 - Widget组件也许它足够通过组件参数传递它 .

  • 0

    使用angular 2内置机制(| async),它会自动取消订阅 .

    some.component.ts:

    this.heroes = this.heroService.getHeroes();
    

    some.component.html:

    <li *ngFor="let hero of heroes | async" (click)="selectedHero=hero">
        <span class="badge">{{hero.id}}</span> {{hero.name}}
    </li>
    

相关问题