我创建了一个 lazyLoad 指令来处理延迟加载组件。
@Directive({
selector: '[lazyComponent]',
})
export class LazyCompDirective<I, T extends LazyLoadedComponent<I>> implements OnInit, OnDestroy {
private _inputs: I|null = null;
private compRef: ComponentRef<T>|null = null;
private readonly subscription = new Subscription();
private type?: Type<T>;
@Input('frLazyComponent') public set component(type: Type<T>) {
if (type) {
this.compRef = this.viewContainerRef.createComponent(type);
this.refreshInputs(this._inputs);
this.type = type;
}
}
@Input() public set inputs(data: I) {
if (this.compRef) {
this.refreshInputs(data);
(this.compRef).hostView.detectChanges();
} else {
this._inputs = data;
}
}
public constructor(private readonly viewContainerRef: ViewContainerRef) {}
ngOnInit(): void {
if (this.type) {
this.compRef = this.viewContainerRef.createComponent(this.type);
this.refreshInputs(this._inputs);
}
}
public ngOnDestroy() {
this.compRef = null;
this.subscription.unsubscribe();
}
private refreshInputs(inputs: I | null) {
if (inputs) {
Object.keys((inputs)).forEach(inputName => {
// @ts-expect-error: skip error
(this.compRef as ComponentRef<unknown>).instance[inputName] = inputs[inputName];
});
}
}
static ngTemplateContextGuard<T extends LazyLoadedComponent<I>, I>(_dir: LazyCompDirective<I, T>, _context: unknown): _context is LazyLoadedComponent<I> {
return true
}
static ngTemplateGuard_inputs<T extends LazyLoadedComponent<I>, I>(_dir: LazyCompDirective<I, T>, _state: I): _state is I {
return true;
}
}
所以我们可以将此属性用作
<ng-template [lazyComponent]="component" [inputs]="componentInput"></ng-template>
我们定义了这个接口,所以我们总是可以有一个带有指令的强类型
export interface LazyLoadedComponent<I> {
inputs?: I;
}
加载我们需要实现这个接口的组件
@Component({
selector: 'lazy-component',
template: '<div>I'm Lazy</div>',
})
export class LazyComponent implements LazyLoadedComponent<LazyComponentInput>, OnInit {
public inputs?: LazyComponentInput;
public constructor(
) {}
public ngOnInit(): void {}
}
惰性组件输入
export interface LazyComponentInput{
a: string,
b: number,
}
我发现
[inputs]
并没有真正检查类型是否有效。
我觉得我的类型检查守卫是错误的,但我不知道我应该如何检查类型。有谁知道我应该如何修复类型检查?