انگولار - بارگذاری پویا کامپوننتها بدون شکستن AoT - انگولار ۲
بنابراین من تلاش میکردم ماژولی ایجاد کنم که مجموعهای از کامپوننتها را گرفته و بهصورت دینامیک بارگذاری کند اما بدون ایجاد مشکل برای AoT. این ثابت شده است که یک چالش است اما من خیلی نزدیک شدهام به جز یک مورد. چگونه میتوانم تمام کامپوننتهایی که در ComponentFactory ذخیره شدهاند را بازیابی کنم؟
در فایل app.module.ts من یک آرایه از کامپوننتها را به forRoot() ماژول بارگذاری داینامیک خود میدهم:
imports: [
DynamicLoadModule.forRoot(dynamicComponents),
]
در dynamic-load.module.ts خود، همهٔ آنها را به ComponentFactory انگولار ۲ اضافه میکنم:
static forRoot(components: any[]) {
return {
ngModule: DynamicLoadModule,
providers: [{
provide: ANALYZE_FOR_ENTRY_COMPONENTS,
useValue: components,
multi: true,
}, {
provide: DynamicLoadService,
useValue: new DynamicLoadService(components)
}]
};
}
حالا مشکل در DynamicLoadService است، که باعث اختلال در AoT میشود. من روش مستند شده export-a-function را امتحان کردهام اما این مشکل را حل نمیکند چون با این روش نمیتوانم components را به عنوان پارامتر به سرویس ارسال کنم. بنابراین، چیزی که در مستندات Angular پیدا شده، راه حلی برای مشکل من ارائه نمیدهد:
let heroServiceFactory = (logger: Logger, userService: UserService) => {
return new HeroService(logger, userService.user.isAuthorized);
};
export let heroServiceProvider =
{ provide: HeroService,
useFactory: heroServiceFactory,
deps: [Logger, UserService]
};
پس من تلاش کردم تا مؤلفهها را به dynamic-load.module خود با استفاده از OpaqueToken منتقل کنم، که این هم کمکی نکرد چون در بهترین حالت مؤلفههای غیرکامپایلشده داشتم و ماژول من انعطافپذیری زیادی را از دست داد.
پس به این نتیجه رسیدم که اگر به یک آرایه از تمام مؤلفهها در ComponentFactory نیاز داشته باشم، فقط به یک روش برای دریافت همه آنها نیاز دارم.
بنابراین، جایی که اکنون از ComponentFactoryResolver برای دریافت یک قالب بر اساس نام استفاده میکنم، باید همه آنها را دریافت کنم، یا حداقل تمام نامهای مؤلفههای موجود در کارخانه را بدست آورم.
if (selectedComponent !== '') {
if (typeof this.currentComponent !== 'undefined') { this.currentComponent.destroy(); }
const components = this.dynamicLoadService.getComponents(), // --> instead of getting a list of available components through this service which needs the factory that blocks AoT, I should just be able to retrieve all available components from the ComponentFactory
component: any = components.find((x) => x.name.toLowerCase().indexOf(selectedComponent) > -1),
compFactory = this.cfr.resolveComponentFactory(component);
this.currentComponent = this.vcr.createComponent(compFactory);
this.currentComponent.instance.data = this.componentData;
}
پاسخ شماره ۱
ویرایش بنابراین پاسخ اول کاملاً مشکل را حل نکرد، اما یک فرد کمککننده دیگر توانست از طریق گیتهاب Angular به من کمک کند تا مشکل را برطرف کنم.
در پایان کد من به شکل زیر به نظر میرسد:
import { NgModule, ANALYZE_FOR_ENTRY_COMPONENTS, Inject } from '@angular/core';
import { DynamicLoadService } from './dynamic-load.service';
import { DynamicLoadComponent } from './dynamic-load.component';
export function DynamicLoadFactory(cmps) {
return new DynamicLoadService(cmps);
}
@NgModule({
declarations: [
DynamicLoadComponent
],
exports: [
DynamicLoadComponent
]
})
export class DynamicLoadModule {
static forRoot(components: any[]) {
return {
ngModule: DynamicLoadModule,
providers: [{
provide: ANALYZE_FOR_ENTRY_COMPONENTS,
useValue: components,
multi: true
},
{
provide: 'ENTRIES',
useValue: components
},
{
provide: DynamicLoadService,
useFactory: DynamicLoadFactory,
deps: [[new Inject('ENTRIES')]]
}]
};
}
}
همانطور که به من گفته شد ANALYZE_FOR_ENTRY_COMPONENTS بخشی از درخت تزریق وابستگی نیست (منبع را اینجا پیدا کنید). بنابراین راهحل فوق با آن مشکل برخورد میکند.
پس پاسخ توسط یک شخص بسیار کمککننده در گیتهاب انگولار به من ارائه شد.
به من پیشنهاد شد که فقط
فقط
ANALYZE_FOR_ENTRY_COMPONENTSرا درDynamicLoadServiceوارد کنید
که اکنون شبیه این به نظر میرسد:
export function DynamicLoadFactory(cmps) {
return new DynamicLoadService(cmps);
}
export class DynamicLoadModule {
static forRoot(components: any[]) {
return {
ngModule: DynamicLoadModule,
providers: [{
provide: ANALYZE_FOR_ENTRY_COMPONENTS,
useValue: components,
multi: true,
}, {
provide: DynamicLoadService,
useFactory: DynamicLoadFactory,
deps: [new Inject(ANALYZE_FOR_ENTRY_COMPONENTS)]
}]
};
}
}
منبع در گیتهاب
