非常教程

AngularJS参考手册

Angular 模块

惰性加载的特性模块

前提条件

对下列知识有基本的了解:

  • 特性模块
  • JavaScript 模块与 NgModules。
  • 常用模块。
  • 特性模块的分类。
  • 路由与导航。

如果需要本页描述的具有两个惰性加载模块的范例应用,参见在线例子 / 下载范例。


高层视角

要想建立一个惰性加载的特性模块,有三个主要步骤:

  1. 创建该特性模块。
  2. 创建该特性模块的路由模块。
  3. 配置相关路由。

建立应用

如果你还没有应用,可以遵循下面的步骤使用 CLI 创建一个。如果已经有了,可以直接跳到 配置路由部分。 输入下列命令,其中的 customer-app表示你的应用名称:

content_copyng new customer-app --routing

这会创建一个名叫 customer-app 的应用,而 --routing 标识生成了一个名叫 app-routing.module.ts 的文件,它是你建立惰性加载的特性模块时所必须的。 输入命令 cd customer-app 进入该项目。

创建一个带路由的特性模块

接下来,你需要一个要路由到的特性模块。要生成一个,请输入下列命令,其中的 customers 是该模块的名字:

content_copyng generate module customers --routing

这会创建一个 customers 目录,其中有两个文件:CustomersModuleCustomersRoutingModuleCustomersModule 扮演的是与客户紧密相关的所有事物的管理员。CustomersRoutingModule 则会处理任何与客户有关的路由。 这样就可以在应用不断成长时保持应用的良好结构,并且当复用本模块时,你可以轻松的让其路由保持完好。

CLI 会把 CustomersRoutingModule 自动导入到 CustomersModule。它会在文件的顶部添加一条 JavaScript 的 import 语句,并把 CustomersRoutingModule 添加到 @NgModuleimports 数组中。

向特性模块中添加组件

要想在浏览器中看出该模块惰性加载成功了,就创建一个组件用来在应用加载 CustomersModule 之后渲染出一些 HTML。在命令行中输入如下命令:

content_copyng generate component customers/customer-list

这会在 customers 目录中创建一个名叫 customer-list 的文件夹,其中包含该组件的四个文件。

就像路由模块一样,CLI 也自动把 CustomerListComponent 导入了 CustomersModule

再添加一个特性模块

为了提供另一个可路由到的地点,再创建第二个带路由的特性模块:

content_copyng generate module orders --routing

这会创建一个名叫 orders 的新文件夹,其中包含 OrdersModuleOrdersRoutingModule

现在,像 CustomersModule 一样,给它添加一些内容:

content_copyng generate component orders/order-list

建立 UI

虽然你也可以在地址栏中输入 URL,不过导航菜单会更好用,而且更常见。 把 app.component.html 中的占位脚本替换成一个自定义的导航,以便你在浏览器中能轻松地在模块之间导航。

src/app/app.component.html

content_copy<h1>
  {{title}}
</h1>

<button routerLink="/customers">Customers</button>
<button routerLink="/orders">Orders</button>
<button routerLink="">Home</button>

<router-outlet></router-outlet>

要想在浏览器中看到你的应用,就在终端窗口中输入下列命令:

content_copyng serve

然后,跳转到 localhost:4200,这时你应该看到 “app works!” 和三个按钮。

惰性加载的特性模块

要想让这些按钮生效,你需要配置一下这些路由模块。

配置路由

这两个特性模块(OrdersModuleCustomersModule)应该挂接到 AppRoutingModule 中,来让路由器知道它们。其结构如下:

惰性加载的特性模块

每个特性模块都是路由器中的一个“门口”。在 AppRoutingModule 中,你配置了一些路由指向这些特性模块(即 OrderModuleCustomersModule)。 通过这种方式,路由器就知道了如何跳转到特性模块。然后,特性模块就把 AppRoutingModuleCustomersRoutingModuleOrdersRoutingModule 连接到一起。这些路由模块会告诉路由器该到哪里去加载相应的组件。

顶层的路由

AppRoutingModule 中,把 routes 数组修改成这样:

src/app/app-routing.module.ts

content_copyconst routes: Routes = [
  {
    path: 'customers',
    loadChildren: 'app/customers/customers.module#CustomersModule'
  },
  {
    path: 'orders',
    loadChildren: 'app/orders/orders.module#OrdersModule'
  },
  {
    path: '',
    redirectTo: '',
    pathMatch: 'full'
  }
];

这些 import 语句没有变化。前两个路径分别路由到了 CustomersModuleOrdersModule。注意看惰性加载的语法:loadChildren 后面紧跟着一个字符串,它指向模块路径,然后是一个 #,然后是该模块的类名。

特性模块内部

接下来看看 customers.module.ts。如果你使用的是 CLI,并遵循本页面中给出的步骤,那么在这里你不必做任何事。 特性模块就像是 AppRoutingModule 和该特性自己的路由模块之间的连接器。AppRoutingModule 导入了特性模块 CustomersModule,而 CustomersModule 又导入了 CustomersRoutingModule

src/app/customers/customers.module.ts

content_copyimport { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { CustomersRoutingModule } from './customers-routing.module';
import { CustomerListComponent } from './customer-list/customer-list.component';

@NgModule({
  imports: [
    CommonModule,
    CustomersRoutingModule
  ],
  declarations: [CustomerListComponent]
})
export class CustomersModule { }

customers.module.ts 文件导入了 CustomersRoutingModuleCustomerListComponent,所以 CustomersModule 类可以访问它们。 接着 CustomersRoutingModule 出现在了 @NgModuleimports 数组中,这让 CustomersModule 可以访问它的路由模块。而 CustomerListComponent 出现在了 declarations 数组中,这表示 CustomerListComponent 属于 CustomersModule

配置该特性模块的路由

接下来的步骤位于 customers-routing.module.ts 中。首先,在文件的顶部使用 JS 的 import 语句导入该组件。然后添加指向 CustomerListComponent 的路由。

src/app/customers/customers-routing.module.ts

content_copyimport { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';

import { CustomerListComponent } from './customer-list/customer-list.component';


const routes: Routes = [
  {
    path: '',
    component: CustomerListComponent
  }
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
export class CustomersRoutingModule { }

注意,path 被设置成了空字符串。这是因为 AppRoutingModule 中的路径已经设置为了 customers,所以 CustomersRoutingModule 中的这个路由定义已经位于 customers 这个上下文中了。也就是说这个路由模块中的每个路由其实都是子路由。

重复这个步骤以导入 OrdersListComponent,并为 orders-routing.module.ts 配置路由树组:

src/app/orders/orders-routing.module.ts (excerpt)

content_copyimport { OrderListComponent } from './order-list/order-list.component';

const routes: Routes = [
  {
    path: '',
    component: OrderListComponent
  }
];

现在,如果你在浏览器中查看该应用,这三个按钮会把你带到每个模块去。

确认它工作正常

你可以使用 Chrome 开发者工具来确认一下这些模块真的是惰性加载的。 在 Chrome 中,按 Cmd+Option+i(Mac)或 Ctrl+Alt+i(PC),并选中 Network 页标签。

惰性加载的特性模块

点击 Orders 或 Customers 按钮。如果你看到某个 chunk 文件出现了,就表示你已经惰性加载并接入了这个特性模块。Orders 和 Customers 都应该出现一次 chunk,并且它们各自只应该出现一次。

惰性加载的特性模块

要想再次查看它或测试本项目后面的行为,只要点击 Network 页左上放的“清除”图标即可。

惰性加载的特性模块

然后,使用 Cmd+r(Mac) 或 Ctrl+r(PC) 重新加载页面。

forRoot()forChild()

你可能已经注意到了,CLI 会把 RouterModule.forRoot(routes) 添加到 app-routing.module.tsimports 数组中。 这会让 Angular 知道 AppRoutingModule 是一个路由模块,而 forRoot() 表示这是一个根路由模块。 它会配置你传入的所有路由、让你能访问路由器指令并注册 RouterService。 在 AppRoutingModule 中使用 forRoot(),在本应用中这只会在顶层模块中写一次。

CLI 还会把 RouterModule.forChild(routes) 添加到各个特性模块中。这种方式下 Angular 就会知道这个路由列表只负责提供额外的路由并且其设计意图是作为特性模块使用。你可以在多个模块中使用 forChild()

forRoot() 包含的注入器配置是全局性的,比如对路由器的配置。forChild() 中没有注入器配置,只有像 RouterOutletRouterLink 这样的指令。


更多关于 NgModule 和路由的知识

你可能还对下列内容感兴趣:

  • 路由与导航。
  • 服务提供商。
  • 特性模块的分类。
AngularJS

Angular 是一个开发平台。它能帮你更轻松的构建 Web 应用。Angular 集声明式模板、依赖注入、端到端工具和一些最佳实践于一身,为你解决开发方面的各种挑战。

AngularJS目录

1.快速上手 | quick start
2.语言服务
3.安全
4.环境准备与部署
5.Service Worker
6.保持最新
7.从 AngularJS 升级
8.服务端渲染
9.Visual Studio 2015 快速上手
10.风格指南
11.国际化
12.测试
13.路由与导航
14. 教程 | Tutorial
15.架构
16.组件与模板
17.表单
18.可观察对象与RxJS
19.引导启动
20.Angular 模块
21.依赖注入
22.HttpClient
23.词汇表
24.AngularJS 应用
25.AngularJS 模块
26.AngularJS 事件
27.AngularJS HTML DOM
28.AngularJS 过滤器
29.AngularJS 控制器
30.AngularJS 指令
31.AngularJS 表达式
32.AngularJS 简介
33.AngularJS 参考手册
34.AngularJS 实例
35.AngularJS 输入验证
36.AngularJS 表单
37.AngularJS SQL
38.AngularJS 表格
39.AngularJS Http
40.AngularJS 包含
41.AngularJS Bootstrap
42.AngularJS API
43.AngularJS ng-checked 指令
44.AngularJS ng-change 指令
45.AngularJS ng-blur 指令
46.AngularJS ng-bind-template 指令
47.AngularJS ng-bind-html 指令
48.AngularJS ng-bind 指令
49.AngularJS ng-app 指令
50.AngularJS Scope(作用域)
51.AngularJS ng-model 指令
52.AngularJS ng-dblclick 指令
53.AngularJS ng-cut 指令
54.AngularJS ng-csp 指令
55.AngularJS ng-copy 指令
56.AngularJS ng-controller 指令
57.AngularJS ng-cloak 指令
58.AngularJS ng-click 指令
59.AngularJS ng-class-odd 指令
60.AngularJS ng-class-even 指令
61.AngularJS ng-class 指令
62.AngularJS ng-keyup 指令
63.AngularJS ng-keypress 指令
64.AngularJS ng-keydown 指令
65.AngularJS ng-init 指令
66.AngularJS ng-include 指令
67.AngularJS ng-if 指令
68.AngularJS ng-href 指令
69.AngularJS ng-hide 指令
70.AngularJS ng-focus 指令
71.AngularJS ng-disabled 指令
72.AngularJS ng-non-bindable 指令
73.AngularJS ng-mouseup 指令
74.AngularJS ng-mouseover 指令
75.AngularJS ng-mousemove 指令
76.AngularJS ng-mouseleave 指令
77.AngularJS ng-mouseenter 指令
78.AngularJS ng-mousedown 指令
79.AngularJS ng-model-options 指令
80.AngularJS ng-model 指令
81.AngularJS ng-list 指令
82.AngularJS ng-style 指令
83.AngularJS ng-srcset 指令
84.AngularJS ng-src 指令
85.AngularJS ng-show 指令
86.AngularJS ng-selected 指令
87.AngularJS ng-repeat 指令
88.AngularJS ng-readonly 指令
89.AngularJS ng-paste 指令
90.AngularJS ng-options 指令
91.AngularJS ng-open 指令
92.AngularJS ng-value 指令
93.AngularJS ng-switch 指令
94.AngularJS ng-submit 指令
95.AngularJS 服务(Service)
96.AngularJS Select(选择框)
97.AngularJS 动画
98.AngularJS 依赖注入