【问题标题】:Angular how to check if module loaded before rendering componentAngular如何在渲染组件之前检查模块是否加载
【发布时间】:2021-08-18 09:41:08
【问题描述】:

我的 Angular 应用程序有一些模块,它们是延迟加载的。在模块 A 的一个组件中,我想在使用 *ngIf 渲染组件中的所有 html 标签之前检查该模块是否已加载。我怎样才能做到这一点?谢谢。

更新 1。

export class CustomerManModule extends AppModuleBase {
  constructor(injector: Injector) {
    super(injector, AppConsts.module.customerMan);

    var localeName = locale();
    this.appService.getLanguage(localeName, AppConsts.module.customerMan).subscribe((messages: any) => {
      let language = new Object();
      language[localeName] = messages;
      loadMessages(language);
    })
  }
}

在我调用loadMessages 函数后,所有的本地化字符串都会被加载,我只想在模块加载时加载这些字符串。之后,该模块的所有组件都需要检查这些字符串是否已加载以继续渲染。

【问题讨论】:

  • 如果你问的是全局加载器,看看这个 SO:stackoverflow.com/questions/54135784/…
  • 谢谢。但这不是我的情况。
  • 我们是在讨论 moduleA 内部的组件还是来自不同的模块?
  • 是的,它在模块 A 中。在模块 A 的构造函数中,我从数据库中为整个模块加载了一些数据。该模块的所有组件都需要在渲染自己之前检查数据是否准备好。
  • 啊,好吧。然后我认为我的回答有点错误,因为您不等待延迟模块加载,而是等待您请求的数据。我现在没时间更新。与此同时,这可能会有所帮助:当您从数据库加载数据时,您很可能会使用 Angular 的 HttpClient。在那里你得到一个 Observable 返回。您可以将此 Observable 存储在自定义服务中,并通过 Async Pipe 从您的组件中访问它。 angular.io/api/common/NgIf(搜索异步)

标签: angular typescript


【解决方案1】:

当一个模块被加载时,它的构造函数被调用。

因此您可以创建自定义ModuleStateService,将其注入模块的构造函数并跟踪其状态。

例子:

@NgModule({
  imports: [CommonModule, SharedServicesModule],
  declarations: [LoginComponent]
})
export class AuthModule {
  constructor(moduleStateService: ModuleStateService) {
    console.log('AuthModule loaded');
    
    moduleStateService.loadedModule('AuthModule');
  }
}

更新 抱歉更新晚了。

您可以将 Route Resolver 与使用一些简单缓存机制(如 shareReplay(1))的服务结合使用,以便只发出一次请求。

//Resolver

@Injectable({
  providedIn: 'root'
})
export class LocalizationResolver implements Resolve<Observable<any>> {
  constructor(private languageService: LanguageService) {}

  resolve(): Observable<any> {
    return this.languageService.loadMessages();
  }
}
// Service, with simplified caching

@Injectable({
  providedIn: 'root'
})
export class LanguageService {
  private cache = {};
  private url = 'https://api.github.com/users';

  constructor(private http: HttpClient) {}

  loadMessages(): Observable<any> {
    if (this.cache['messages']) {
      return this.cache['messages'];
    }
    this.cache['messages'] = this.http.get(this.url).pipe(shareReplay(1)); // todo error handling
    return this.cache['messages'];
  }
}
// Route configuration:

const ROUTES = [
  { path: '', redirectTo: 'home', pathMatch: 'full' },
  { path: 'home', component: ContainerComponent },
   ...
  {
    path: 'resolver',
    component: WithResolverComponent,
    resolve: { users: LocalizationResolver }
  }
];

Stackblitz

【讨论】:

  • 感谢您的回答。这个可以检查模块是否被加载。但是我怎样才能继续渲染组件呢?组件如何等待加载的模块继续渲染?
  • 您可以创建一个解析器,它在被观察的布尔值上使用pipe(filter()) 监听可观察对象。这样,在加载模块之前,路由不会加载。如果您不想阻止路由,而只是阻止内容,则可以在组件模板内部使用*ngIf 来做同样的事情
  • 我必须为每个组件创建解析器还是可以使用通用解析器?我不喜欢创建多个解析器。如果我可以为所有组件使用通用解析器,请给我一个示例。谢谢。
猜你喜欢
  • 2019-08-09
  • 2013-05-21
  • 2018-02-08
  • 1970-01-01
  • 2016-06-09
  • 2021-04-19
  • 2021-12-09
  • 2019-05-28
相关资源
最近更新 更多