我有一个非常大的组件,可以加载超过1000个数据元素。这些数据元素通过服务填充,该服务仅被调用一次。在最初的实现中,每次初始化组件时都会调用该服务,这是我认为问题所在。因此,我创建了一个只在祖父组件中调用一次的共享服务。
组件层次结构如下:
可以看出,BlockComponent
正在所有三个TypeComponents
中使用。三个不同BlockComponent
中显示的TypeComponents
数据相同(尽管标题 @Input)。 TypeComponent
的第一次初始化加载很好,但是当它们之间切换时,加载时间超过3秒,我认为这是不合理的。有没有办法加快加载时间?
我知道下面分享了很多代码。如果我知道如何在 webpack 项目中创建一个Plunker。
共享data.service.ts
import { Injectable } from '@angular/core';
import { DataResolver } from '../../blocking/data/data.resolver';
import { Data } from 'si-data-model';
import { Observable } from 'rxjs/Observable';
import { Logger } from 'ngx-data-utils';
@Injectable()
export class DataService {
data: Data[] = []; // shared data
dataObs$: Observable<Data[]>;
logger: Logger;
completed = false; // used to signal whether the service has completed to components
constructor(private resolver: DataResolver,
logger: Logger) {
this.logger = logger;
}
ngOnInit() {
this.logger.debug('Data Service initialized.');
}
ngOnDestroy() {
this.logger.debug('Data Service destroyed.');
}
load() {
return this.resolver.resolve(); // retrieves the data elements from a web service
}
initData() {
this.dataObs$ = this.load();
this.dataObs$.subscribe((res: Data[]) => {
this.data = res;
this.completed = true;
});
}
}
add.component.ts
import { Component, OnDestroy, OnInit } from '@angular/core';
import { DataService } from '../../shared/data/data.service';
@Component({
selector: 'add',
templateUrl: './add.component.html',
styleUrls: ['./add.component.scss']
})
export class AddComponent implements OnInit, OnDestroy {
radioUrl: string;
constructor(private service: DataService) {
console.log('Add component built');
}
ngOnInit() {
this.service.initData();
console.log('Add component initialized');
}
ngOnDestroy() {
console.log('Add component destroyed');
}
}
type1.component.ts
import { Component, OnDestroy, OnInit } from '@angular/core';
@Component({
selector: 'type1',
templateUrl: './type1.component.html',
styleUrls: ['./type1.component.scss']
})
export class Type1Component implements OnInit, OnDestroy {
title = 'Add Block Stuff';
constructor() {
console.log('Type1 component built');
}
ngOnInit() {
console.log('Type1 component initialized');
}
ngOnDestroy() {
console.log('Type1 component destroyed');
}
onType1Change($event: any) {
console.log($event);
}
}
block.component.ts
import { Component, OnDestroy, OnInit, Output, EventEmitter, Input } from '@angular/core';
import { Logger } from 'ngx-data-utils';
import { Observable } from 'rxjs/Observable';
import { Data } from 'si-data-model';
import { DataService } from '../../shared/data/data.service';
@Component({
selector: 'block',
templateUrl: './block.component.html',
styleUrls: ['./block.component.scss']
})
export class BlockComponent implements OnInit, OnDestroy {
dataLoaded = false;
labels = ['Label1', 'Label2', 'Label3', 'Label4',
'Label5'];
selected: any[] = [];
data1: string;
data2: string;
data3: string;
data4: string;
data5: string;
data6: string;
datas: Data[] = [];
@Output() change: EventEmitter<any> = new EventEmitter();
@Input() title: string;
@Input() data: Data[];
// private criteriaCodes = [6, 2, 3, 11, 29, 25];
constructor(private logger: Logger,
private dataService: DataService) {
// TODO
}
ngOnInit() {
this.display();
this.logger.debug('BlockComponent initialized.');
}
ngOnDestroy() {
this.logger.debug('BlockComponent destroyed.');
}
initData () {
this.dataService.data.forEach((dt: Data) => {
this.datas.push(dt);
this.dataLoaded = true;
});
}
display() {
if (this.dataService.completed)
this.initData();
}
propagateChange() {
this.change.emit(this.selected); // doesn't do anything yet
}
}
block.component.html
<div class="row" *ngIf="dataLoaded">
<div class="row">
<div class="col-md-4">
<label>{{'DATA.BLOCK.LABEL1' | translate}}</label>
<select class="custom-select form-control" [(ngModel)]="data1" (change)="propagateChange()">
<option *ngFor="let c of data[0].value">{{c.code}} - {{c.description}}</option>
</select>
</div>
<div class="col-md-4">
<label>{{'DATA.BLOCK.LABEL2' | translate}}</label>
<select class="custom-select form-control" [(ngModel)]="data2" (change)="propagateChange()">
<option *ngFor="let mt of data[1].value">{{mt.code}} - {{mt.description}}</option>
</select>
</div>
<div class="col-md-4">
<label>{{'DATA.BLOCK.LABEL3' | translate}}</label>
<select class="custom-select form-control" [(ngModel)]="data3" (change)="propagateChange()">
<option *ngFor="let pem of data[2].value">{{pem.code}} - {{pem.description}}</option>
</select>
</div>
</div>
<div class="row">
<div class="col-md-4">
<label>{{'DATA.BLOCK.LABEL4' | translate}}</label>
<select class="custom-select form-control" [(ngModel)]="data4" (change)="propagateChange()">
<option *ngFor="let tt of data[3].value">{{tt.code}} - {{tt.description}}</option>
</select>
</div>
<div class="col-md-4">
<label>{{'DATA.BLOCK.LABEL5' | translate}}</label>
<select class="custom-select form-control" [(ngModel)]="data5" (change)="propagateChange()">
<option *ngFor="let cl of data[4].value">{{cl.code}} - {{cl.description}}</option>
</select>
</div>
<div class="col-md-4">
<label>{{'DATA.BLOCK.LABEL6' | translate}}</label>
<input type="text">
</div>
</div>
</div>
答案 0 :(得分:0)
看起来add.component.ts
每次重新初始化时都会重新获取数据?
你能做到这一点:
initData() {
if (!this.data) {
this.dataObs$ = this.load();
this.dataObs$.subscribe((res: Data[]) => {
this.data = res;
this.completed = true;
});
}
}
然后,一旦数据被检索,它就不会重新加载数据。
关于子组件,它们中至少有一个是循环遍历 EVERY 元素并创建自己的数据数组副本?
initData () {
this.dataService.data.forEach((dt: Data) => {
this.datas.push(dt);
this.dataLoaded = true;
});
相反,请尝试使用getter:
export class BlockComponent implements OnInit, OnDestroy {
get datas(): Data[] {
return this.dataService.data;
}
// ...
}