角度材料对话框和热模块重新加载

Aug*_*ner 8 webpack-hmr angular-material2 angular

到目前为止,我已成功完成以下工作:

✓HMR(热模块重新加载)设置
✓角度(5)和材料运行良好
✓打开一个对话框(下面的代码片段)

// ...
constructor(private dialog: MatDialog){}
//...
public openDialog(){
    this.dialogRef = this.dialog.open(someDialogComponent, {
      width: '300px'
    });
}
Run Code Online (Sandbox Code Playgroud)

✓在对话框或对话框的父控制器上进行更改
✓MMR被触发(yay)
✖对话框挂起死机状态,由于对话框和背景被"卡住"而无法点击,页面基本上被冻结

我试图挂钩ngOnInitngOnDestroy在父或对话框控制器中关闭对话框引用,如果存在,我也尝试过dialog.closeAll(),但这没有用.此外,理想情况下,对话框不必关闭,但我似乎无法修复此僵尸对话框问题.

有没有遇到过这个?

sea*_*ass 5

我一直在为此苦苦挣扎,但现在找到了一个不太理想的解决方案。在 hmr destroy 事件期间,它会从 DOM 中删除任何有角度的对话框。

const elements = document.getElementsByClassName('cdk-overlay-container');
for (let i = 0; i < elements.length; i++) {
  elements[i].innerHTML = '';
}
Run Code Online (Sandbox Code Playgroud)

然后在 OnInit 中,我们重新创建所有打开的对话框,并传入它们的数据。唯一的问题是此解决方案保留了旧的对话框实例,因此它们不能从后台单击中关闭。但是,如果对话框上有一个关闭按钮,那么它将正确关闭。StateService 中的 OpenDialogs 属性可能会更改为包含 componentInstances 的 TemplateRef[],这可能会解决问题,但我不确定。

无论如何,在对 dialogs + hmr 的官方支持到来之前,这是一个黑客解决方案。

app.module.ts

export class AppModule {
  constructor(private state: StateService, public dialog: MatDialog) { }

  OnInit(store) {
    if (store !== undefined) {
      this.state.SetState(store.State);

      for (let i = 0; i < this.state.OpenDialogs.length; i++) {
        const t = this.state.OpenDialogs[i].componentInstance;
        this.dialog.open(t.constructor, { data: t.data });
      }
    }
  }

  OnDestroy(store) {
    this.state.OpenDialogs = this.dialog.openDialogs;
    store.State = this.state;

    const elements = document.getElementsByClassName('cdk-overlay-container');
    for (let i = 0; i < elements.length; i++) {
      elements[i].innerHTML = '';
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

状态.service.ts:

import { Injectable } from '@angular/core';
import { MatDialogRef } from '@angular/material';

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

  public OpenDialogs: MatDialogRef<any>[];

  constructor() {
  }

  public SetState(_state: StateService) {
    this.OpenDialogs = _state.OpenDialogs;
  }
}
Run Code Online (Sandbox Code Playgroud)

主文件

import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';


if (environment.production) {
  enableProdMode();
}

// tslint:disable-next-line:no-shadowed-variable
function bootstrap(AppModule) {
  return platformBrowserDynamic().bootstrapModule(AppModule)
    .then(moduleRef => {
      if (environment.hmr) {
        if (module['hot']) {
          module['hot']['accept']();
          if (moduleRef.instance['OnInit']) {
            if (module['hot']['data']) {
              moduleRef.instance['OnInit'](module['hot']['data']);
            }
          }
          if (moduleRef.instance['OnStatus']) {
            module['hot']['apply']((status) => {
              moduleRef.instance['OnStatus'](status);
            });
          }
          if (moduleRef.instance['OnCheck']) {
            module['hot']['check']((err, outdatedModules) => {
              moduleRef.instance['OnCheck'](err, outdatedModules);
            });
          }
          if (moduleRef.instance['OnDecline']) {
            module['hot']['decline']((dependencies) => {
              moduleRef.instance['OnDecline'](dependencies);
            });
          }

          module['hot']['dispose'](store => {
            if (moduleRef.instance['OnDestroy']) {
              moduleRef.instance['OnDestroy'](store);
            }
            moduleRef.destroy();
            if (moduleRef.instance['AfterDestroy']) {
              moduleRef.instance['AfterDestroy'](store);
            }
          });
        }
      }

      return moduleRef;
    });
}

bootstrap(AppModule);
Run Code Online (Sandbox Code Playgroud)