2017-11-23 12 views
0

Angular4を初めて使用しています。基本的な質問と貧しい私の英語のために申し訳ありません。私は自分の問題を説明するために最善を尽くします。絶対に破壊されないコンポーネントでAngular2/4脱退が観察される

私は現在、観測可能なサービスを使ってメッセージを共有するウェブサイトを開発しています。

しかし、問題が発生しました。 ここは私のexample file structureです。 working Plunker

「ユーザーコンポーネント」から「ヘッダーコンポーネント」受信メッ​​セージがありました。

ヘッダコンポーネント:

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(); 
    } 
} 

と "ウィジェット成分"、 "製品コンポーネント" からメッセージを受信しました。

ウィジェットコンポーネント:

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を作成します。 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); 
    } 
} 

ので、ヘッダーの右側にある情報は「ユーザーページ」を表示します。 「商品ページ」をクリックすると、ウィジェットの下の情報に「NIKE」と表示されます。しかし同時に、ヘッダー情報も "NIKE"に変わります。私はそれが起こらないようにします。

コンポーネントが破棄されたときに私は退会しなければならないことを知っていますが、この場合、ヘッダーは決して破壊されません。だから、おそらく....私はそれを解除する必要があります "ユーザーコンポーネント"破棄し、再び "ユーザーコンポーネント" initを購読するが、私はそれを行う方法がわからない、またはこのアイデアが悪いです。

私はいくつかの指示を与えてください、任意の意見は助けになるでしょう。 ありがとうございました。

+0

は、なぜあなたが言及したコンポーネントの関連する部分を追加していけませんか? –

+1

ご意見ありがとうございます、私は私の質問を更新します。 – Ryan

答えて

0

私は、あなたが1つのshareAction$を使用して、あまりにも多くのことをやっているという問題があると思います。ヘッダー情報とウィジェット用にSubjectを作成してみませんか?

また、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); 
    } 
} 

のように、それをこのように、より具体的な名前を与えて試してみてください/退会:作成されたときに購読し、破壊されたときに購読を停止します。

また、タイプとしてanyを避けることを検討してください。ミスマッチタイプを引き起こす変更がある場合、コンパイラは何か問題があるとあなたに伝えます。

CurrentProductはサービスを通じてグローバルに共有する必要がありますか?製品コンポーネント - ウィジェットコンポーネントでのみ使用する場合は、コンポーネントのパラメータを渡すだけで十分です。

+1

ありがとう、あなたは私の一日を節約! はい、現在の製品を他のコンポーネントとグローバルに共有する必要があります。コードを単純化するだけです。 お寄せいただきありがとうございます。それは本当に助け、非常に感謝します! – Ryan

0

角度2+組み込みのメカニズム(|非同期)を使用すると、自動的に登録解除されます。

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> 
関連する問題