目录
NgMoudle常用模块
| NgModule | 导入自 | 为何使用 |
|---|---|---|
|
| 当你想要在浏览器中运行应用时 | |
|
| 当你想要使用 | |
|
| 当要构建模板驱动表单时(它包含 | |
|
| 当要构建响应式表单时 | |
RouterModule | @angular/router | 要使用路由功能,并且你要用到 |
|
| 当你要和服务器对话时 |
常用元数据
| 属性 | 说明 |
|---|---|
| 属于该模块的可声明对象(组件、指令和管道)的列表。
组件、指令和管道只能属于一个模块。 如果尝试把同一个类声明在多个模块中,编译器就会报告一个错误。 小心,不要重复声明从其它模块中直接或间接导入的类。 | |
|
| 依赖注入提供商的列表。 Angular 会使用该模块的注入器注册这些提供商。 如果该模块是启动模块,那就会使用根注入器。 当需要注入到任何组件、指令、管道或服务时,这些服务对于本注入器的子注入器都是可用的。 惰性加载模块有自己的注入器,它通常是应用的根注入器的子注入器。 惰性加载的服务是局限于这个惰性加载模块的注入器中的。 如果惰性加载模块也提供了 其它外部模块中的组件也会使用它们自己的注入器提供的服务实例。 要深入了解关于多级注入器及其作用域,参见服务提供商。 |
| 要折叠(Folded)进本模块中的其它模块。折叠的意思是从被导入的模块中导出的那些软件资产同样会被声明在这里。 特别是,这里列出的模块,其导出的组件、指令或管道,当在组件模板中被引用时,和本模块自己声明的那些是等价的。 组件模板可以引用其它组件、指令或管道,不管它们是在本模块中声明的,还是从导入的模块中导出的。 比如,只有当该模块导入了 Angular 的 你可以从 | |
| 可供导入了自己的模块使用的可声明对象(组件、指令、管道类)的列表。 导出的可声明对象就是本模块的公共 API。 只有当其它模块导入了本模块,并且本模块导出了 默认情况下这些可声明对象都是私有的。 如果本模块没有导出 导入某个模块并不会自动重新导出被导入模块的那些导入。 模块 B 不会因为它导入了模块 A,而模块 A 导入了 一个模块可以把另一个模块加入自己的 重新导出可以让模块被显式传递。 如果模块 A 重新导出了 | |
| 要自动启动的组件列表。 通常,在这个列表中只有一个组件,也就是应用的根组件。 Angular 也可以用多个引导组件进行启动,它们每一个在宿主页面中都有自己的位置。 启动组件会自动添加到 | |
|
| 那些可以动态加载进视图的组件列表。 默认情况下,Angular 应用至少有一个入口组件,也就是根组件 路由组件也是入口组件,因为你需要动态加载它们。 路由器创建它们,并把它们扔到 DOM 中的 虽然引导组件和路由组件都是入口组件,不过你不用自己把它们加到模块的 Angular 会自动把模块的 而那些使用不易察觉的 动态组件加载在除路由器之外的大多数应用中都不太常见。如果你需要动态加载组件,就必须自己把那些组件添加到 |
服务的作用域与唯一性
在聊服务提供商的作用域之前先明确几个概念,什么是急性加载?所谓急性记载就是在程序启动的时候所有模块都被加载。什么是惰性加载?所谓惰性加载就是在真正应用到具体模块的时候再加载指定的模块,也就是按需加载,那么怎么才能实现按需加载那?其实就是应用了路由的模块而已,也叫惰性加载模块。
对于服务而言,如果我们需要在某个组件中应用某个服务那么我们需要在它的构造函数中把对象注入进来,但是对于被注入的对象是怎么来的其实还是有很多需要说明的地方。对于急性加载而言,没有什么特别的地方,如果把服务注册为全局的话(providedIn:"root"),那么在整个应用中都是可以被访问的,换句话说是全局唯一,全局单例的,因为再获取被注入对象的时候,Angular注册器会检查当前是否存在这个对象,存在就直接提供了,不存在创建一个新的并维护这个对象的状态,以供别的地方再使用。对于惰性加载而言,被注入对象的生成方式是不同的,当惰性加载某个模块的时候Angular会先为该模块创建一个子的注册器,然后把根注册器上的服务添加到子注册器上,在该模块上下文中获取的对象时是在子注册器上去操作的,所以就会存在服务对象的作用域与对象单例唯一的问题。
作用域
@Injectable({providedIn:xxxModule/root'})通过providedIn来指定根注册器,还是指定xxxModule的注册器。
唯一性
对于普通服务来说,指定providedIn root,在appModule中提供就可以了。不过对于某个模块同时提供了服务和可声明对象(组件,指令,管道),这时候我们需要该模块被导入到appModule中(提供服务),同时也希望它被导入到其它模块中(提供指令等),这时候当这个其它模块被加载的时候就会创建一个新的子注册器也就是说会创建一个新的服务对象,本来希望服务对象是单例的,现在很明显是多个了,那么如何解决这样的单例问题那?
import { ModuleWithProviders, NgModule, Optional, SkipSelf } from '@angular/core';
import { UserService } from './user.service';
import { UserServiceConfig } from './user.service';
@NgModule({
imports: [ CommonModule ],
declarations: [ ],
exports: [ ],
providers: [ UserService ]
})
export class CoreModule {
constructor (@Optional() @SkipSelf() parentModule: CoreModule) {
if (parentModule) {
throw new Error();
}
}
static forRoot(config): ModuleWithProviders {
return {
ngModule: CoreModule,
providers: [
{provide: UserServiceConfig, useValue: config }
]
};
}
}
--------------------------------------------------------------
// 在appModule中import的时候直接调用
CoreModule.forRoot(),
惰性加载模块使用
1. 在appModule中导入appRouterModule
2. 在appRouterModule中配置路由
const routes: Routes = [
{
path: 'path1',
loadChildren: './xxx/xxx.module#xxxModuleClass1'
},
{
path: 'path2',
loadChildren: './xxx/xxx.module#xxxModuleClass2'
},
{
path: '',
redirectTo: '',
pathMatch: 'full'
}
];
@NgModule({
imports: [
RouterModule.forRoot(routes)
],
exports: [RouterModule],
providers: []
})
3. 在特性子模块中导入子路由Module
4. 在子路由模块中配置组件
const routes: Routes = [
{
path: '',
component: xxxComponent
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
Angular路由
基本使用方式
// 占位符,接收的位置
<router-outlet></router-outlet>
// 跳转方式1
<a routerLink="/xxx" routerLinkActive="active"/>
// 跳转方式2
this.router.navigate(['/xxx', { id: id }]);
------------------------------------------------------
// 指定name
<router-outlet name="xxx"></router-outlet>
// 跳转到指定name的outlet
<a [routerLink]="[{ outlets: { xxx: ['pathname'] } }]"/>
// 清空
this.router.navigate([{ outlets: { xxx: null }}]);
常用模块部件
| 路由器部件 | 含义 |
|---|---|
|
| 为激活的 URL 显示应用组件。管理从一个组件到另一个组件的导航 |
| 一个独立的 NgModule,用于提供所需的服务提供商,以及用来在应用视图之间进行导航的指令。 | |
|
| 定义了一个路由数组,每一个都会把一个 URL 路径映射到一个组件。 |
|
| 定义路由器该如何根据 URL 模式(pattern)来导航到组件。大多数路由都由路径和组件类构成。 |
|
| 该指令( |
|
| 这个指令把可点击的 HTML 元素绑定到某个路由。点击带有 |
|
| 当 HTML 元素上或元素内的 |
|
| 为每个路由组件提供提供的一个服务,它包含特定于路由的信息,比如路由参数、静态数据、解析数据、全局查询参数和全局碎片(fragment)。 |
|
| 路由器的当前状态包含了一棵由程序中激活的路由构成的树。它包含一些用于遍历路由树的快捷方法。 |
| 链接参数数组 | 这个数组会被路由器解释成一个路由操作指南。你可以把一个 |
| 路由组件 | 一个带有 |
常用事件一览
| 路由器事件 | 说明 |
|---|---|
| 本事件会在导航开始时触发。 | |
RouteConfigLoadStart | |
RouteConfigLoadEnd | 本事件会在惰性加载了某个路由后触发。 |
| 本事件会在路由器解析完 URL,并识别出了相应的路由时触发 | |
| 本事件会在路由器开始 Guard 阶段之前触发。 | |
ChildActivationStart | 本事件会在路由器开始激活路由的子路由时触发。 |
ActivationStart | 本事件会在路由器开始激活某个路由时触发。 |
GuardsCheckEnd | 本事件会在路由器成功完成了 Guard 阶段时触发。 |
ResolveStart | |
| 本事件会在路由器成功完成了路由的解析(Resolve)阶段时触发。 | |
ChildActivationEnd | 本事件会在路由器激活了路由的子路由时触发。 |
ActivationEnd | 本事件会在路由器激活了某个路由时触发。 |
| 本事件会在导航成功结束之后触发。 | |
| 这个事件会在导航由于意料之外的错误而失败时触发。 | |
Scroll | 本事件代表一个滚动事件。 |
ActivatedRoute中常用的路由参数
| 属性 | 说明 |
|---|---|
|
| 路由路径的 |
|
| 一个 |
|
| 一个 |
|
| 一个 |
|
| 一个适用于所有路由的 URL 的 fragment(片段)的 |
|
| 要把该路由渲染到的 |
|
| 用于该路由的路由配置信息,其中包含原始路径。 |
|
| 当该路由是一个子路由时,表示该路由的父级 |
|
| 包含该路由的子路由列表中的第一个 |
|
| 包含当前路由下所有已激活的子路由。 |
路由守卫
路由守卫的作用是控制路由的行为,比如检查用户是否有权限访问等。Angular中支持的路由守卫如下。
1. 用CanActivate来处理导航到某路由的情况,多用来检查是否登录。
2. 用CanActivateChild来处理导航到某子路由的情况。
3. 用CanDeactivate来处理从当前路由离开的情况.
4. 用Resolve在路由激活之前获取路由数据。
5. 用CanLoad来处理异步导航到某特性模块的情况。
在分层路由的每个级别上,你都可以设置多个守卫。 路由器会先按照从最深的子路由由下往上检查的顺序来检查 CanDeactivate() 和 CanActivateChild() 守卫。 然后它会按照从上到下的顺序检查 CanActivate() 守卫。 如果特性模块是异步加载的,在加载它之前还会检查 CanLoad() 守卫。 如果任何一个守卫返回 false,其它尚未完成的守卫会被取消,这样整个导航就被取消了。
最后DEMO地址。
本文梳理了Angular中的NgModule常用元数据,详细解释了服务的作用域与唯一性,特别是惰性加载模块的服务管理。此外,还介绍了Angular路由的基本使用、模块部件、路由参数和路由守卫,包括不同类型的路由守卫及其在导航过程中的执行顺序。
503

被折叠的 条评论
为什么被折叠?



