角度保存 /还原组件状态



我正在开发一个具有多名布局的Angular 7应用程序。每个选项卡都包含一个可以引用其他嵌套组件的组件。

当用户选择一个新/另一个选项卡时,当前选项卡上显示的组件被破坏了(我不只是隐藏它们,并且我遵循了这种模式,因为打开的选项卡可能很多,而且似乎更快的解决方案大部头书(。由于加载组件可能是昂贵的(可能是从API中检索到的大量数据(,我试图在选项卡容器中持续存在每个组件状态(在整个应用程序寿命中它都活着(。

一切都按预期运行,但我认为我使用了很多代码来满足我的需求,希望一切都会更简单(并且不太容易出现错误(。

在这里,下面是关于我如何设法完成的摘录。首先,我创建了一个抽象类,该类别中的每个组件都应扩展。

export abstract class TabbedComponent implements OnInit, OnDestroy {
  abstract get componentName(): string;
  tab: LimsTab;
  host: TabComponent;
  private _componentInitialized = false;
  constructor(
    private _host: TabComponent,
  ) {
    this.host = _host;
  }
  get componentInitialized(): boolean {
    return this._componentInitialized;
  }
  ngOnInit(): void {
    this.tab = this.host.tab;
    this.loadDataContext();
    this._componentInitialized = true;
  }
  ngOnDestroy(): void {
    this.saveDataContext();
  }
  get dataContext() {
    return this.tab.dataContext;
  }
  protected abstract saveDataContext(): void;
  protected abstract loadDataContext(): void;
}

loadDataContextsaveDataContext在混凝土组件中实现,并包含逻辑以保存/检索组件实例值。此外,我已经使用_componentInitialized来理解该组件何时将其生命周期挂钩oninitit:组件可以从父亲那里接收@Input,而ngOnChanges是从我看到的OnInit之前触发的。

这里是具体实现的示例:

@Component({
   ...
})
export class MyComponent extends TabbedComponent implements OnChanges {
  private qualityLotTests: QualityLotTestListItem[];
  private _selectedTest: QualityLotTestListItem;
  @Input()
  selectedQualityLot: string;
  @Output()
  selectedTest: EventEmitter<QualityLotTestListItem> = new EventEmitter<QualityLotTestListItem>();
  constructor(_host: TabComponent, private qualityLotService: QualityLotService) {
    super(_host);
  }
  get componentName(): string {
    return 'QualityLotTestListComponent';
  }
  ngOnChanges(changes: SimpleChanges): void {
    if (this.componentInitialized) {
      // before calling loadData I need to restore previous data (if any) 
      // this allow me to undestrand if loaded data filters has changed 
      // I know I restored it if onInit has executed
      // if componentInitialized -> onInit has been executed and input parameters passed from parent are changed
      this.loadData();
    }
  }
  protected saveDataContext(): void {
    this.dataContext[this.componentName].selectedQualityLot = this.selectedQualityLot;
    this.dataContext[this.componentName].state = this.state;
    this.dataContext[this.componentName].qualityLotTests = this.qualityLotTests;
    this.dataContext[this.componentName].selectedSampleTestIDs
        = this.selectedSampleTestIDs;
    this.dataContext[this.componentName]._selectedTest = this._selectedTest;
  }
  protected loadDataContext(): void {
    let previouslySelectedQualityLot: string;
    if (this.dataContext[this.componentName]) {
      previouslySelectedQualityLot = this.dataContext[this.componentName].selectedQualityLot;
      this.state = this.dataContext[this.componentName].state || this.state;
      this.qualityLotTests = this.dataContext[this.componentName].qualityLotTests;
      this._selectedTest = this.dataContext[this.componentName]._selectedTest;      
    } else {
      this.dataContext[this.componentName] = {};
    }
    this.selectedTest.emit(this._selectedTest);
    if (this.qualityLotTests && previouslySelectedQualityLot === this.selectedQualityLot) {
      this.dataStateChange(<DataStateChangeEvent>this.state);
    } else {
      this.loadData();
    }
  }

  loadData(): void {
    if (this.selectedQualityLot) {
      this.loading = true;
      this.qualityLotService
        .getQualityLotTests(this.selectedQualityLot)
        .subscribe(
          qualityLotTests => {
            this.qualityLotTests = qualityLotTests;
            this.gridData = process(this.qualityLotTests, this.state);
            this.loading = false;
          },
          error => (this.errorMessage = <any>error)
        );
    } else {
      this.qualityLotTests = null;
      this.gridData = null;
      this.state = {
        skip: 0,
        take: 10
      };
      this.selectedSampleTestIDs = [];
      this.selectedTest.emit(null);
    }
  }
  public dataStateChange(state: DataStateChangeEvent): void {
    this.loading = true;
    this.state = state;
    this.gridData = process(this.qualityLotTests, this.state);
    this.loading = false;
  }
}

您认为我如何改进上面的代码?

我已经在此处加载了我的应用程序的提取

我们可以看到一个用于澄清的plunkr吗?

我认为,没有所有对象继承,您可以利用三种常见的模式来保持状态。

  1. 容器/演示文稿(也称为智能和哑巴(组件

在这里,您将获取并将数据存储在容器组件中,并通过@Input()传递到演示组件。您可以在这里破坏演示组件,而不必担心失去状态。

  1. 路由器导航

最好使用路由器导航的概念显示所需的容器组件,不仅要利用现有的实践,而且让用户始终知道他们在应用程序中的位置。

  1. 最重要的一个国家管理库 - 我使用NGRX,但听到了有关Akira和Ngxs的好消息。

,如果您从未使用过一些学习曲线redux模式,您可以将应用程序状态存储在一个地方,使其成为不变并从任何组件中引用。

最新更新