通过 router.navigate 方法加载组件时未在 NgOnInit 中调用共享服务的方法

Shared service's method not called in NgOnInit while loading the component through router.navigate method

我有一个详细组件和 child 组件概述和联系方式,我使用共享服务来共享一个数组 ImageMap,它在从其上的服务检索后由详细信息更新初始化并由 children 在各自的 init 方法上订阅和访问。当我导航到 child 组件时,手动在地址栏中键入地址,child 组件的 ngOnInit 中的代码段会加载以设置来自共享服务的数组值,而通过 router.navigate 导航时单击按钮时,除了 NgOnInit 中的那部分之外,其他所有内容都会被加载。请帮我解决这个问题。我哪里出错了?

//账户详情component.html

<h3>You selected brand {{item_name}}</h3>
<p>
    <button (click)="showOver()" class="btn btn-primary">Overview</button>
    <button (click)="showCon()" class="btn btn-info">Contact</button>
</p>
<router-outlet></router-outlet>
<button (click)="gotoAccounts()" class="btn btn-warning">Back</button>

//数据共享Service.ts

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

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

  private dataObs$ =  new Subject();



     getData() {
        return this.dataObs$;
                }

updateData(data) {
    this.dataObs$.next(data);
                  }

 constructor() { }
}

//账户详情Component.ts

import { Component, OnInit} from '@angular/core';
import { ActivatedRoute,Router,ParamMap } from '@angular/router';
import { ImageFetchService } from '../image-fetch.service';
import { DatashareService } from '../datashare.service';

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

public item_id;
public item_name;
public imageMap;
public errorMsg;
constructor(private route: ActivatedRoute,private router:Router,private 
imageService: ImageFetchService,
private dataService: DatashareService) { }

ngOnInit() {

//let id = parseInt(this.route.snapshot.paramMap.get('id'));
//this.item_id=id;

this.route.paramMap.subscribe((params: ParamMap)=>
{
  let id = parseInt(params.get('id'));
  this.item_id=id;
  let sel_name = params.get('name');
  this.item_name=sel_name;
  console.log(this.item_id,this.item_name);
}  )

 this.imageService.getImages().subscribe(data =>{ this.imageMap=data;

 this.dataService.updateData(this.imageMap);},
                                              error => this.errorMsg=error);




 }



  showOver()
  {
               let sel_name= this.item_name?this.item_name:null;

                this.router.navigate(['overview',{"name":sel_name}],
                {relativeTo:this.route})


   }

   showCon()
   {
       let sel_name= this.item_name?this.item_name:null;

       this.router.navigate(['contact',{"name":sel_name}],
       {relativeTo:this.route})

   }
  }

//账户概览Component.ts

import { Component, OnInit,Input,OnDestroy,NgZone } from '@angular/core';
import {NgbCarouselConfig} from '@ng-bootstrap/ng-bootstrap';
import {map} from 'rxjs/operators';
import {HttpClient} from '@angular/common/http';
import { ActivatedRoute,Router,ParamMap } from '@angular/router';
import { DatashareService } from '../datashare.service';
import { Subscription } from 'rxjs/Subscription';


@Component({
  selector: 'app-account-overview',
  templateUrl: './account-overview.component.html',
  styleUrls: ['./account-overview.component.css'],
  providers: [NgbCarouselConfig]
})
export class AccountOverviewComponent implements OnInit,OnDestroy {
private subscription: Subscription = new Subscription();
public imageArray;
 public imageMap;
 public errorMsg;
 public selected_name;
  constructor(config: NgbCarouselConfig, private _http: HttpClient
  ,private route:ActivatedRoute,private dataService: DatashareService
  ,private zone:NgZone) {
    // customize default values of carousels used by this component tree
    config.interval = 2000;
    config.keyboard = false;
    config.pauseOnHover = false;
  }

  ngOnInit() {

   this.route.paramMap.subscribe((params: ParamMap)=>
        {
            let name =params.get('name');
            this.selected_name=name;
            console.log(this.selected_name);
        })

        this.subscription.add(this.dataService.getData().subscribe(data => { //<== added this

            this.zone.run(()=>{
                this.imageArray = data;
            })

        }))







  }

  ngOnDestroy() {
        // unsubscribe to ensure no memory leaks
        this.subscription.unsubscribe();
    }




}

尝试 return dataObs$ 在您的 DatashareService.ts 中作为 Observable,并用 BehaviorSubject 替换您的主题。

import { BehaviorSubject } from 'rxjs/Rx';

export class DatashareService {

    private dataObs$ = new BehaviorSubject<any>({});

    getData() {
        return this.dataObs$.asObservable();
    }

    updateData(data) {
        this.dataObs$.next(data);
    }

    constructor() { }
}

使用 BehaviourSubject 导致子组件中的 subscribe 方法触发两次,第一次是初始值 {},然后是最后更新的值。所以我将其更改为不需要初始值的ReplaySubject。

import { ReplaySubject } from 'rxjs/Rx';

export class DatashareService {

    private dataObs$ = new ReplaySubject<any>(1);

    getData() {
        return this.dataObs$.asObservable();
    }

    updateData(data) {
        this.dataObs$.next(data);
    }

    constructor() { }
}