Angular 16独立组件如何实现类似@NgModule的组合导出?
我现在使用Angular 16的独立组件,想要实现类似@NgModule的组合导入/导出组件功能,就像ng-zorro-antd里的NzMenu组件那样,通过多个组件协作完成一项功能,其原NgModule实现如下:
@NgModule({ imports: [BidiModule, CommonModule, PlatformModule, OverlayModule, NzIconModule, NzNoAnimationModule, NzOutletModule], declarations: [ NzMenuDirective, NzMenuItemComponent, NzSubMenuComponent, NzMenuDividerDirective, NzMenuGroupComponent, NzSubMenuTitleComponent, NzSubmenuInlineChildComponent, NzSubmenuNoneInlineChildComponent ], exports: [NzMenuDirective, NzMenuItemComponent, NzSubMenuComponent, NzMenuDividerDirective, NzMenuGroupComponent] }) export class NzMenuModule {}
Angular官方仅在《Standalone components for library authors》中提到了NgModule里的组合导入方式,原文内容:
Such an array could be imported by applications using NgModules and added to the @NgModule.imports.
请问不使用NgModule的话,怎么实现相同的组件组合导出效果?
实现方案
在Angular 16+的独立组件体系中,你可以通过创建常量数组组合对外暴露的组件/指令,替代NgModule的exports功能,同时统一处理依赖导入,具体步骤如下:
1. 定义组件组合常量
把需要对外提供的组件、指令统一放到一个数组里,等价于NgModule的exports数组:
// 示例:nz-menu-exports.ts import { NzMenuDirective, NzMenuItemComponent, NzSubMenuComponent, NzMenuDividerDirective, NzMenuGroupComponent } from './components'; export const NZ_MENU_COMPONENTS = [ NzMenuDirective, NzMenuItemComponent, NzSubMenuComponent, NzMenuDividerDirective, NzMenuGroupComponent ];
2. 统一管理依赖导入
针对原NgModule中imports里的依赖(比如CommonModule、NzIconModule等),可以创建一个共享的依赖数组,让所有关联的独立组件复用,避免重复编写:
// 示例:nz-menu-deps.ts import { CommonModule } from '@angular/common'; import { NzIconModule } from 'ng-zorro-antd/icon'; // 其他需要的依赖... export const NZ_MENU_DEPS = [ CommonModule, NzIconModule, // 原NgModule中的其他导入项 ];
然后每个独立组件在配置standalone: true时,直接导入这个共享依赖数组:
@Component({ selector: 'nz-menu-item', standalone: true, imports: [...NZ_MENU_DEPS], template: '...' }) export class NzMenuItemComponent {}
3. 对外提供便捷导入入口
在库的入口文件(比如index.ts)中,把组件组合数组和所有组件一起导出,让使用者能像导入NgModule一样便捷:
// index.ts export * from './nz-menu-exports'; export * from './components';
使用者在自己的独立组件中,只需导入这个组合数组就能一次性引入所有需要的组件:
import { NZ_MENU_COMPONENTS } from 'your-library/menu'; @Component({ standalone: true, imports: [...NZ_MENU_COMPONENTS], template: ` <nz-menu> <nz-menu-item>菜单项</nz-menu-item> <nz-sub-menu title="子菜单"> <nz-menu-item>子菜单项</nz-menu-item> </nz-sub-menu> </nz-menu> ` }) export class YourComponent {}
额外注意点
- 原NgModule中声明的私有组件(比如
NzSubmenuInlineChildComponent这类不需要对外暴露的),只需保持独立组件状态,不用加入组合数组,内部组件直接引用即可。 - 如果需要同时兼容NgModule和独立组件,可以把这个组合数组加入到NgModule的
imports中,兼顾两种使用场景,和官方文档提到的方式一致。
内容的提问来源于stack exchange,提问作者ZheXian

