Angular ivy 中的 renderComponent 带有额外的 component/directive 声明

renderComponent in Angular ivy with extra component/directive declarations

这里是在ivy中渲染动态惰性组件的例子:

import { ɵrenderComponent as renderComponent, Injector } from '@angular/core';

@Component({
  selector: 'app-root',
  template: `
    <app-lazy></app-lazy>
  `
})
export class AppComponent {
  constructor(injector: Injector) {
    import('./lazy.component').then(({ LazyComponent }) => {
      renderComponent(LazyComponent, {
        injector,
        host: 'app-lazy'
      });
    });
  }
}

如果我们需要在lazy.component中使用额外的component/directive怎么办?

您需要一个自定义装饰器

import {
  Component,
  Type,
  ɵComponentDef as ComponentDef,
  ɵDirectiveDef as DirectiveDef,
  ɵPipeDef as PipeDef
} from '@angular/core';

@Component(...)
@ComponentDeps({
   directives: [...], //***extra component/directive you want***
   pipes: [...] //***extra pipe, like: JsonPipe...***
})
export class LazyComponent{
 ...
}



export interface ComponentDepsConfig {
  directives?: Type<any>[];
  pipes?: Type<any>[];
}
function getDirectiveDef<T>(t: Type<T>): DirectiveDef<T> {
  if (t['ɵdir']) {
    return t['ɵdir'] as DirectiveDef<T>;
  }
  if (t['ɵcmp']) {
    return t['ɵcmp'] as ComponentDef<T>;
  }
  throw new Error('No Angular definition found for ' + t.name);
}
function getDirectiveDefs(types: Type<any>[]): DirectiveDef<any>[] {
  return types.map(t => getDirectiveDef(t));
}

function getPipeDef<T>(t: Type<T>): PipeDef<T> {
  if (t['ɵpipe']) {
    return t['ɵpipe'] as PipeDef<T>;
  }
  throw new Error('No Angular definition found for ' + t.name);
}

export function getPipeDefs(types: Type<any>[]): PipeDef<any>[] {
  return types.map(t => getPipeDef(t));
}
export function ComponentDeps(config: ComponentDepsConfig) {
  return (componentType: Type<any>) => {
    const def = componentType['ɵcmp'] || componentType['ngComponentDef'];
    // directives or components
    def.directiveDefs = [
      ...getDirectiveDefs(config.directives || [])
    ];
    // pipes
    def.pipeDefs = [
      ...getPipeDefs(config.pipes || [])
    ];
  };
}
function setScopeOnDeclaredComponents(moduleType: Type<any>, component: any) {
  const transitiveScopes = ɵtransitiveScopesFor(moduleType);
  const componentDef = component[ɵNG_COMP_DEF];
  if (!componentDef) {
    console.error('not define comp')
  }
  ɵpatchComponentDefWithScope(componentDef, transitiveScopes);
}