如何使用 Angular 在 HMR 期间保留状态

2024-01-17

在 Angular 中,有没有办法在模块热重新加载后保留应用程序状态?与 VueJS 中发生的情况类似:

到目前为止,我已经按照几个教程让 HMR 正常工作,但它所做的只是重新加载应用程序,而不进行实际的页面刷新。满载更快,是的。但仍然没有达到应有的水平。

有人让它真正发挥作用吗?

PS:有关系https://github.com/beeman/tutorial-angular-cli-hmr/issues/4 https://github.com/beeman/tutorial-angular-cli-hmr/issues/4


我尝试了上面的鲈鱼方法,但在使其发挥作用时遇到了一些困难。我确实发现它非常有帮助且信息丰富。利用他的想法,我能够创建一个新的 Angular 6 应用程序,并让应用程序状态通过 HMR 构建得以保留。我在 Github 上创建了一个项目,这样其他人如果想尝试的话可以把它拉下来,因为这是最好的学习方式。阅读代码注释并检查控制台日志,以了解事情发生的顺序以及它们如何工作。

https://github.com/ermcgrat/NgStarter https://github.com/ermcgrat/NgStarter

克隆项目,执行 npm install,然后使用“运行应用程序”npm 运行开始”。尝试更改 AppComponent 中的代码,看看 hmr 是如何工作的。

然而简而言之,我能够通过创建状态服务并在我的应用程序中利用它来实现状态持久性。应用程序模块 and hmr引导程序。首先,我从 Angular CLI 团队指定的基本 HMR 功能开始:

https://github.com/angular/angular-cli/wiki/stories-configure-hmr https://github.com/angular/angular-cli/wiki/stories-configure-hmr

这将使 HMR 正常工作,但不会保留状态。我延长了hmr.ts文件来保存模块被处置(卸载)时的状态。当新模块被评估时,它将从 HMR 模块读取保存的状态并将其注入到我们的新模块中:

hmr.ts

export const hmrBootstrap = (module: any, bootstrap: () => Promise<NgModuleRef<any>>) => {
  module.hot.accept();

  bootstrap().then(mod => {

    // Attach a dispose handler. When this module is replaced, we will first run this code before
    // evaluating the new module. (eg. running main.ts)
    module.hot.dispose(data => {

      if (mod.instance.hmrOnDestroy) {
        mod.instance.hmrOnDestroy(data);
      }

      const appRef: ApplicationRef = mod.injector.get(ApplicationRef);
      const elements = appRef.components.map(c => c.location.nativeElement);
      const makeVisible = createNewHosts(elements);
      mod.destroy();
      makeVisible();
    });

    // Does this module have an hmrOnInit method for us to run?
    // And is there state data from previous unloaded module to initalize?
    let prevData;
    if (module.hot.data && module.hot.data.appState) {
      prevData = module.hot.data.appState;
    }
    if (mod.instance.hmrOnInit && prevData) {
      mod.instance.hmrOnInit(prevData);
    }

  });
};

这是我们的 AppModule,实现了hmrOnInit and hmrOnDestroy上面使用的方法。值得注意的是 hmrOnInit 如何通过状态服务恢复应用程序状态(如果存在)。

应用程序模块.ts

export class AppModule {

  constructor(private appRef: ApplicationRef, private stateService: AppStateService) { }

  hmrOnInit(prevState: any) {
    if (prevState) {
      this.stateService.saveAppState(prevState);
      // change detection.
      this.appRef.tick();
    }
  }

  hmrOnDestroy(data: any) {
    // Here we will increment our hmrBuilds counter, and then save our state to
    // data (module.hot.data), so that it will be available to the new module.
    const hmrBuilds = this.stateService.getHmrBuilds() + 1;
    this.stateService.saveHmrBuilds(hmrBuilds);
    data.appState = this.stateService.getAppState();
  }
}

最后是应用程序状态服务。唯一特别棘手的事情是我们本质上以两种形式维护应用程序状态。其中 1 个是用于同步访问的普通旧版对象(这对于 HMR 重建是必要的,因为无法保证模块中的异步函数在评估新模块之前完成)。第二个是我们的应用程序状态的可观察版本,以便各个组件可以轻松观察状态的更改/更新。

应用程序状态服务.ts

export class AppStateService {

  // attach various component states to this object
  // We maintain an object for synchronous use by the HMR, and an Observable for use by the application and its templates.
  private appState: IAppState = { hmrBuilds: 0 };
  private appStateSubject = new BehaviorSubject<IAppState>({ hmrBuilds: 0 });
  public appState$: Observable<IAppState> = this.appStateSubject.asObservable();

  constructor() { }

  public getAppState() {
    return this.appState;
  }

  public getHmrBuilds(): number {
    return this.appState.hmrBuilds ? this.appState.hmrBuilds : 0;
  }

  public saveAppState(newState: IAppState) {
    this.appState = newState;
    this.appStateSubject.next(newState);
  }

  public saveHmrBuilds(buildNum: number) {
    this.appState.hmrBuilds = buildNum;
  }

}

最后,任何应用程序组件现在都可以观察到这一点应用程序状态$并在其组件代码或模板中使用它。

我还想指出,这种在 HMR 构建之间维护状态的方法本质上会导致单一事实来源。我认为像这样的州立图书馆ngrx会与这样的东西完美结合。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 Angular 在 HMR 期间保留状态 的相关文章

随机推荐

  • 在 JavaScript 中使用正则表达式删除下划线

    就像标题所说 我想用正则表达式删除字符串中的下划线 这就是我所拥有的 function palindrome str str str toLowerCase replace a zA Z g s g 0 9 g if str split r
  • 为什么java在SSL握手期间不发送客户端证书?

    我正在尝试连接到安全的网络服务 尽管我的密钥库和信任库已正确设置 但握手失败 经过几天的沮丧 无休止的谷歌搜索和询问周围的每个人 我发现唯一的问题是java选择在握手期间不将客户端证书发送到服务器 具体来说 服务器请求客户端证书 CN Ro
  • Gmail API 配额单位费用

    我们正在构建一项利用 Gmail API 的服务 为了了解我们在扩展过程中的成本 我想知道使用 Gmail API 的成本是多少 我已按照以下说明进行操作https developers google com gmail api v1 re
  • 从 Portlet 中删除自定义权限/操作

    我已经能够根据 Liferay Plugins SDK 中的示例定义自定义 portlet 操作 权限 https github com liferay liferay plugins tree master portlets sample
  • 如何在 Ubuntu 14.04 中使用 systemctl

    我尝试在 Ubuntu 14 04 中执行以下命令 systemctl enable now docker cleanup dangling images timer 我也用 sudo 尝试过 我尝试用 service 和 systemd
  • 按最后一个数组条目字段值过滤结果

    具有此文档结构 为了简洁省略不相关的字段 id 0 partn date ISODate 2015 07 28T00 59 14 963Z is partner true date ISODate 2015 07 28T01 00 32 7
  • Javascript,写入txt文件另存为UNICODE

    我有2根弦 希望首先创建一个 txt 文件 然后将字符串保存为 unicode function WriteFile file str str2 var tmp real url replace 20 g var WshNetwork ne
  • 根据 java.io/java.nio 进行阻塞

    我刚刚读 使用流的类位于两个包中 java io 和 java nio 以前实现的类 输入 输出 I O 阻塞 当字节被读 写时 进程中 它们对于其他执行线程变得不可用 这 后一个包提供非阻塞 I O 并提高了性能 并且想更多地了解这一点
  • Automapper 可以忽略 void 方法吗?

    我是 Automapper 的新手 所以我不确定这是否可行 我想映射一个类 但让它忽略无效的方法 下面是我的代码的说明 当我运行这个时 我收到以下异常消息 AutoMapper AutoMapperMappingException 类型的未
  • 如何将 JavaScript 函数传递给 Silverlight?

    我正在评估 JavaScript Silverlight 互操作功能 并且已经能够使用 JavaScript 创建 Silverlight 实例并调用其方法 但是 我现在需要一种将 JavaScript 回调函数传递给 Silverligh
  • iPhone OS 中的核心动画中的“图像错位”是什么?

    Instruments 表示存在由核心动画制作的 未对齐的图像 这意味着什么 更新 我在 Instruments app gt 核心动画中看到了这一点 我希望了解有关您在哪里看到此内容的更多信息 但我怀疑它指的是未像素对齐的图像 Quart
  • UDP 服务与亚马逊网络服务

    再会 我在一个硬件项目的基于云的系统中经常使用 AWS 使用 SimpleDB 和提供的通知服务很棒 然而 我需要 AWS 上的一个后端来监听传入的请求 处理请求并将其发送回特定地址 某种 UDP 服务 我可以轻松地为其编写一个 C C 应
  • Linq GroupBy 将每个空值作为一个组

    我有一个具有可为 null int 属性 GroupId 的对象 有了这个对象的列表 我想对此 GroupId 执行 GroupBy 操作 但如果我这样做 所有空值将形成一个组 例子 对象 1 GroupId NULL 对象 2 Group
  • 拉取镜像时设备上没有剩余空间

    在 Windows 10 Build 14393 下使用 Docker 1 13 0 9795 当我尝试运行最新的 python 映像 即 3 6 时 出现 设备上没有剩余空间 的情况 gt docker run it python Una
  • 根据 Java 日期在 Postgres 中保存时间戳

    我有一个 Postgres 数据库 其中有一个包含时间戳的表 timeOfProcessing TIMESTAMP 我有一个 Java 日期时间值 java util Date dateTime 并希望将其值存储在该时间戳字段中 没有时区
  • 设置响应 ContentType 的中间件

    在我们基于 ASP NET Core 的 Web 应用程序中 我们需要以下内容 某些请求的文件类型应获得自定义 ContentType 作为响应 例如 map应该映射到application json 在 完整 的 ASP NET 4 x
  • 具有捆绑和缩小功能的 ASP.NET MVC 4 应用程序,为什么在调试模式下启用缩小?

    我刚刚将 ASP NET MVC 3 项目迁移到 MVC 4 NET 4 0 并安装了 NuGet 包Microsoft AspNet Web Optimization为了支持 CSS 和 JavaScript 的捆绑和缩小 我几乎已经完成
  • 如何跟踪 Magento 从哪里调用模板?

    我正在与 Magento 合作 请看下面的代码 有没有一种简单的方法可以找到 HTML 所在的位置 IE 有某种我可以使用的痕迹吗 在管理中转到系统 gt 配置 gt 开发者 从左上角的 配置范围 选择中选择一个商店 然后 调试 部分中将出
  • Git diff 工具对多个提交以及其间的其他提交进行比较

    我们有一个工作流程 其中提交的代码需要由其他开发人员审核 在简单的情况下 可以使用 git diff oldhash newhash gt diff txt 来完成 并将其上传到我们的审查委员会 但是有没有办法在多个提交之间创建差异并排除其
  • 如何使用 Angular 在 HMR 期间保留状态

    在 Angular 中 有没有办法在模块热重新加载后保留应用程序状态 与 VueJS 中发生的情况类似 到目前为止 我已经按照几个教程让 HMR 正常工作 但它所做的只是重新加载应用程序 而不进行实际的页面刷新 满载更快 是的 但仍然没有达