angular - 如何用组件替换容器?
问题描述
我有必须显示不同组件的侧边栏组件取决于事件数据。
现在在应用程序的任何地方我使用Subject()
数据发送命令:
{data: {}, type: "showSearch"}
{data: {}, type: "showResultSearch"}
{data: {}, type: "showUserBlock"}
{data: {}, type: "showContacts"}
然后在SideBarComponent
我听这些数据并应用于变量类型:
this.events.listen().subject((data) => {
this.type = data.type;
);
然后在模板里面SideBarComponent
我做:
<app-search *ngIf="type === 'showSearch'"></app-search>
<app-result-search *ngIf="type === 'showResultSearch'"></app-result-search>
<app-user-block *ngIf="type === 'showUserBlock'"></app-user-block>
<app-contracts *ngIf="type === 'showContacts'"></app-contacts>
那么,如何更优雅地解决这个问题呢?现在我有超过 10 个组件。
解决方案
您可以使用对象并动态渲染组件,而不是块*ngIf
甚至是块,如下所示:ngSwitch
角度 < 9:
模块:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { ContactsComponent } from './contacts.component.ts';
import { ResultSearchComponent } from './result-search.component.ts';
import { SearchComponent } from './search.component.ts';
import { UserBlockComponent } from './user-block.component.ts';
const ENTRY_COMPONENTS = [
ContactsComponent,
ResultSearchComponent,
SearchComponent,
UserBlockComponent,
];
const DECLARATIONS = [
...ENTRY_COMPONENTS,
AppComponent,
];
@NgModule({
bootstrap: [AppComponent],
declarations: DECLARATIONS,
imports: [BrowserModule],
entryComponents: ENTRY_COMPONENTS,
})
export class AppModule {}
组件:
import { Component, Type } from '@angular/core';
import { switchMap } from 'rxjs/operators';
import { ContactsComponent } from './contacts.component';
import { ResultSearchComponent } from './result-search.component';
import { SearchComponent } from './search.component';
import { UserBlockComponent } from './user-block.component';
const componentsMapper = {
showContacts: ContactsComponent,
showResultSearch: ResultSearchComponent,
showSearch: SearchComponent,
showUserBlock: UserBlockComponent,
// others
};
角 9:
模块:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
@NgModule({
bootstrap: [AppComponent],
declarations: [AppComponent],
imports: [BrowserModule],
})
export class AppModule {}
组件:
import { Component, Type } from '@angular/core';
import { switchMap } from 'rxjs/operators';
const componentsMapper = {
showContacts: import('./contacts.component').then(({ ContactsComponent }) => ContactsComponent),
showResultSearch: import('./result-search.component').then(({ ResultSearchComponent }) => ResultSearchComponent),
showSearch: import('./search.component').then(({ SearchComponent }) => SearchComponent),
showUserBlock: import('./user-block.component').then(({ UserBlockComponent }) => UserBlockComponent),
// others
};
任何Angular版本的通用代码(9 到以下):
模板:
<ng-template [ngComponentOutlet]="ngComponentOutlet$ | async"></ng-template>
组件:
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
readonly ngComponentOutlet$ = this.events.listen().pipe(
switchMap(data => this.loadComponent(data.type))
);
async loadComponent(type: string): Promise<Type<any>> {
return await componentsMapper[type];
}
}
您可能已经注意到,两个版本之间的区别仅在于,在 Angular 9 中,不需要将动态组件添加到entryComponents部分,@NgModule
甚至不需要添加到声明中。代码可以根据需要真正动态地导入。
阅读更多:
https://medium.com/angular-in-depth/asynchronous-modules-and-components-in-angular-ivy-1c1d79d45bd3
https://medium.com/angular-in-depth/lazy-load-components-in-angular-596357ab05d8
https://netbasal.com/welcome-to-the-ivy-league-lazy-loading-components-in-angular-v9-e76f0ee2854a
推荐阅读
- rust - 通用特征实现中的生命周期
- javascript - 新闻框的进度条
- python - Python/Pandas - 根据文件名中的日期读取文件夹中的多个文件
- javascript - Bot Framework:如何阻止 ChoicePrompt 重新提示
- javascript - JavaScript:将对象数组转换为通用哈希图
- button - 当我在 Slack 上单击 HeroCard 中的一个按钮时,两个按钮都会动画
- asterisk - 通过任何 Asterisk API 访问 RTP 流量
- prolog - SICStus Prolog 中的验证属性
- struts2 - 建议从 struts 1.2 迁移到 struts 2.x?
- c# - ASP.NET MVC - 检查上传的文件是 .EXE 还是 PDF 文件