【问题标题】:Angular4 ngOnInit rxjs/Subject not workingAngular4 ngOnInit rxjs/主题不工作
【发布时间】:2017-09-26 13:14:26
【问题描述】:

我有Directive,其中有Subscription 用于调整图表大小

import {Directive, ElementRef, HostListener, Input, OnDestroy, OnInit} from '@angular/core';
import {Subscription} from 'rxjs/Subscription';
import echarts from 'echarts';
import 'echarts/theme/macarons';
import {ChartService} from '../service/chart/chart.service';

@Directive({selector: '[appECharts]'})
export class EChartsDirective implements OnInit, OnDestroy {
  element: ElementRef;
  subscription: Subscription;
  @Input() eChartsOptions: any;
  @Input() theme = 'macarons';
  private chart;

  constructor(element: ElementRef, private chartsService: ChartService) {
    this.element = element;
  }

  ngOnInit() {
    this.subscription = this.chartsService.chartChange.subscribe((str) => {
      this.resizeChart(str);
    });
    this.chart = echarts.init(this.element.nativeElement, this.theme);
    if (this.eChartsOptions) {
      this.chart.setOption(this.eChartsOptions);
    }
  }

  ngOnDestroy() {
    if (this.chart) {
      this.chart = null;
    }
    this.subscription.unsubscribe();
  }

  resizeChart(str: string) {
    console.log('resize from=' + str);
    setTimeout(() => {
      if (this.chart) {
        console.log('resize');
        this.chart.resize();
      }
    }, 500);
  }

  @HostListener('window:resize')
  onResize() {
    this.resizeChart('window');
  }
}

图表服务:

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

@Injectable()
export class ChartService {
  chartChange = new Subject<string>();
  orderChartChanged = new Subject<any[]>();
  private orderCharts: any[];

  setChartData(orderCharts) {
    this.orderCharts = orderCharts;
    this.orderChartChanged.next(this.orderCharts);
  }

  updateCharts(srt: string) {
    console.log('from=' + srt);
    this.chartChange.next(srt);
  }
}

我调用 updateCharts 方法的组件

import {Component, ElementRef, OnDestroy, OnInit, ViewChild} from '@angular/core';
import {ChartHttpService} from '../../shared/service/chart/chart-http.service';
import {MdSnackBar} from '@angular/material';
import {Subscription} from 'rxjs/Subscription';
import {ChartService} from '../../shared/service/chart/chart.service';
import echarts from 'echarts';
import 'echarts/theme/macarons';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnDestroy, OnInit {
  chartSubscription: Subscription;
  @ViewChild('chart1') element: ElementRef;
  chart2;

  constructor(private chartService: ChartService,
              private chartHttpService: ChartHttpService,
              public snackBar: MdSnackBar) {
  }

  ngOnInit() {
    const chart = echarts.init(this.element.nativeElement, 'macarons');
    this.chartSubscription = this.chartService.orderChartChanged
      .subscribe(
        (response: any) => {
          const option = response.orderAmount;
          chart.setOption(option);
          setTimeout(() => {
            chart.resize();
          }, 500);
          this.chart2 = option;
          this.chartService.updateCharts('home');
        }
      );
    this.chartHttpService.orderCharts(this.snackBar);
  }

  ngOnDestroy() {
    this.chartSubscription.unsubscribe();
    this.chart2 = null;
  }

  onResize() {
    this.chartService.updateCharts('btn');
  }

}

ChartHttpService:

import {Injectable} from '@angular/core';
import {MdSnackBar} from '@angular/material';
import {HttpClient} from '@angular/common/http';

import {TranslateService} from '@ngx-translate/core';
import {Observable} from 'rxjs/Observable';
import 'rxjs/Rx';
import {SnackBarUtils} from '../snack-bar-utils';
import {environment} from '../../../../environments/environment';
import {ChartService} from './chart.service';

@Injectable()
export class ChartHttpService {
  private static orderCharts = 'json/chart/ordersChart';

  constructor(private http: HttpClient,
              private chartService: ChartService,
              private translate: TranslateService) {
  }

  orderCharts(snackBar: MdSnackBar) {
    const url = environment.apiUrl + ChartHttpService.orderCharts;
    this.http.get(url)
      .catch(error => {
        return Observable.throw(error);
      })
      .subscribe(
        response => this.chartService.setChartData(response),
        error => SnackBarUtils.showLocalizedSnackBar(this.translate, snackBar, 'msg.error')
      );
  }
}

还有html组件:​​

<div class="row">
  <div class="col-lg-6 col-md-6 col-xs-12 col-sm-6">
    <md-card>
      <div class="box-header">Base Line</div>
      <div #chart1 style="height: 300px;"></div>
    </md-card>
  </div>
  <div class="col-lg-6 col-md-6 col-xs-12 col-sm-6">
    <md-card>
      <div class="box-header">Stacked Line</div>
      <ng-container *ngIf="chart2">
        <div appECharts [eChartsOptions]="chart2" style="height: 300px;"></div>
      </ng-container>
    </md-card>
  </div>
  <button (click)="onResize()">Resize</button>
</div>

所以问题是当我在浏览器中按refreshf5 时,updateCharts 方法在HomeComponent 中调用但chartChange 我猜主题不起作用,因为在EChartsDirective 订阅没有调用方法resizeChart,这个问题只在refreshf5之后出现。 如果我点击 Resize btn,一切正常。

所以我不知道为什么,但EChartsDirective 中的subscriptionrefreshf5 之后没有调用resizeChart

任何想法为什么会发生?

更新: 只有chart2 有问题,我添加了chart1,我在HomeComponent -&gt; ngOnInit 中手动添加了init(没有指令),当我打电话时

setTimeout(() => {
            chart.resize();
          }, 500);

它有效,但当然,问题只是订阅,但仍然)

更新2: 改为:

   ngOnInit() {
   this.chart = echarts.init(this.element.nativeElement, this.theme);
   if (this.eChartsOptions) {
     this.chart.setOption(this.eChartsOptions);
   }
   this.subscription = this.chartsService.chartChange.subscribe((str) => {
     this.resizeChart(str);
   });
 }

什么都没变

browser refreshF5 之后登录

from=home-123

点击后登录以调整 btn 大小

from=xxx        chart.service.ts:16
resize from=xxx echarts.directive.ts:37 
resize          echarts.directive.ts:40 

【问题讨论】:

    标签: angular subscription


    【解决方案1】:
     ngOnInit() {
        this.subscription = this.chartsService.chartChange.subscribe((str) => {
          this.resizeChart(str);
        });
        this.chart = echarts.init(this.element.nativeElement, this.theme);
        if (this.eChartsOptions) {
          this.chart.setOption(this.eChartsOptions);
        }
      }
    

    在这里你设置this.chart 你订阅Subject,而在resizeChart你检查this.chart是否被定义。它可能会失败,因为此时它仍然为空。在订阅Subject之前尝试设置this.chart

    【讨论】:

    • 在 resizeChart 的控制台中记录了什么?它甚至被调用了吗?
    • resizeChart 没有日志,好的,所以我添加了 this.resizeChart(str);在 EChartsDirective 的 ngOnInit 方法中,在每个图表初始化之后,我都有调整大小的效果,所以它对我有用
    【解决方案2】:

    好的,所以我添加了 this.resizeChart(str);在 EChartsDirective 的 ngOnInit 方法中,在每个图表初始化之后,我都有调整大小的效果,所以它对我有用

    【讨论】:

      猜你喜欢
      • 2023-03-21
      • 2018-01-09
      • 1970-01-01
      • 2018-05-31
      • 1970-01-01
      • 2022-07-31
      • 2020-12-13
      • 2018-08-14
      • 1970-01-01
      相关资源
      最近更新 更多