Angular 学习笔记 (十) - Modules和动态Component
一. Angular的Module
模块Module是组织应用和使用外部库扩展应用的最佳途径。
Angular 自己的库都是 NgModule,比如 FormsModule
、HttpClientModule
和 RouterModule
。 很多第三方库也是 NgModule,比如 Material Design、 Ionic 和 AngularFire2。
NgModule 把组件、指令和管道打包成内聚的功能块,每个模块聚焦于一个特性区域、业务领域、工作流或通用工具。
模块还可以把服务加到应用中。 这些服务可能是内部开发的(比如你自己写的),或者来自外部的(比如 Angular 的路由和 HTTP 客户端)。
模块可以在应用启动时急性加载,也可以由路由器进行异步的惰性加载。
NgModule 的元数据会做这些:
-
声明某些组件、指令和管道属于这个模块。
-
公开其中的部分组件、指令和管道,以便其它模块中的组件模板中可以使用它们。
-
导入其它带有组件、指令和管道的模块,这些模块中的元件都是本模块所需的。
-
提供一些供应用中的其它组件使用的服务。
每个 Angular 应用都至少有一个模块,也就是根模块。 你可以引导那个模块,以启动该应用。
对于那些只有少量组件的简单应用,根模块就是你所需的一切。 随着应用的成长,你要把这个根模块重构成一些特性模块,它们代表一组密切相关的功能集。 然后你再把这些模块导入到根模块中。
当输入一个命令生成一个新的模块:
ng generate module heroes
之后会自动生成一个heroes.module.ts文件
1 2 3 4 5 6 7 8 9 | import { NgModule } from '@angular/core' ; import { CommonModule } from '@angular/common' ; @NgModule({ declarations: [], imports: [ CommonModule ] }) export class HeroesModule { } |
引入NgModule:
- Declarations:
注册的组件、指令和管道模块。
Declarations具有唯一性,当Component在一个Module中加入Declaration,就不能出现在其它模块的Declaration中
- imports:
包含此模块要使用的声明的其他模块。Angular CLI会在这个属性中自动为我们定义CommonModule。它一个模块是否总是在Angular应用中使用,因为它包含了所有的我们通常喜欢使用的内置指令和管道。
Imports不具有唯一性,但代码中要避免循环引用。(A import B, B import A)
- exports:
Angular构件,在声明中定义并可供其他模块使用。这是模块的公共API。它定义了什么公开访问或不公开访问。其他没有显式导出的东西都是被认为是私有的或模块内部的。
- providers:
由模块提供且可访问的服务从应用程序的任何模块,用于依赖注入
- bootstrap:
应用程序的主要组件,当应用程序启动。此属性只在主应用程序中设置一次一个AppModule模块,通常是AppComponent。
通常情况下,你不应该更改它,除非有特别的理由。
二. Lazy-load
默认情况下,NgModule 都是急性加载 (Eager-load) 的,也就是说它会在应用加载时尽快加载,所有模块都是如此,无论是否立即要用。对于带有很多Routes的大型应用,考虑使用惰性加载 —— 一种按需加载 NgModule 的模式。
惰性加载可以减小初始包的尺寸,从而减少加载时间。
要使用lazy-load,定义Route如下:
1 const routes: Routes = [ 2 { 3 path: 'items', 4 loadChildren: './items/items.module#ItemComponent' 5 } 6 ];
如果使用最新的Typescript标准,代码还可以这样写:
1 const routes: Routes = [ 2 { 3 path: 'items', 4 loadChildren: () => import('./items/items.module').then(m => m.ItemsModule) 5 } 6 ];
这需要ts达到最新es标准,在tsconfig.ts修改:
{ "compileOnSave": false, "compilerOptions": { "baseUrl": "./", "outDir": "./dist/out-tsc", "sourceMap": true, "declaration": false, ”module“: esnext, "moduleResolution": "node", "emitDecoratorMetadata": true, "experimentalDecorators": true, "target": "es5", "typeRoots": [ "node_modules/@types" ], "lib": [ "es2017", "dom" ] } }
三. 动态Component
Dynamic component用于Component不事先在template中实现的情况,可以用ComponentFactory产生一个Component。
(这种case也可以被其它技术路线替代,比如NgIf)
示例:
需要动态加载这样一个简单的Component:弹出一个警告框,message:string作为输入,提供一个close按钮。
1 import { Component, EventEmitter, Input, Output } from "@angular/core"; 2 3 @Component({ 4 selector: "app-alert", 5 templateUrl: "./alert.component.html", 6 styleUrls: ['./alert.component.css'] 7 }) 8 export class AlertComponent { 9 10 @Input() message:string; 11 12 @Output() close = new EventEmitter<void>(); 13 14 onClose() { 15 this.close.emit(); 16 } 17 18 }
在下函数中实现动态创建:
1 private showErrorAlert(message: string) { 2 const alertComponentFactory = this.componentFactoryResolver.resolveComponentFactory( 3 AlertComponent 4 ); 5 const hostViewContainerRef = this.alertHost.viewContainerRef; 6 hostViewContainerRef.clear(); 7 8 const componentRef = hostViewContainerRef.createComponent(alertComponentFactory); 9 10 componentRef.instance.message = message; 11 this.closeSub = componentRef.instance.close.subscribe(() => { 12 this.closeSub.unsubscribe(); 13 hostViewContainerRef.clear(); 14 }); 15 }
其中 alertHost 是主视图中的html template元素
Angular11以下的版本在app.module.ts中,使用这个模块需要:
@NgModule({ entryComponents: [AlertComponent] //Expire in Angular 11 })
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
2019-04-19 两种语言实现设计模式(C++和Java)(一:工厂模式)
2019-04-19 [转] CMake