架构师_程序员

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 42|回复: 0

[Angular] Angular4.0踩坑之路:探索子路由和懒加载

[复制链接]
跳转到指定楼层
楼主
发表于 3 天前
随着需求的增加,项目的功能也渐渐复杂起来。这个时候,需要将项目模块化,将组件、指令和管道打包成内聚的功能块,正好可以探索一下Angular4中的子路由以及模块的懒加载。

之前在开发的时候,已经在根模块实现了简单的路由功能,可以总结为以下三个步骤:

1、在app.module.ts文件中加载路由库,并且在@NgModule中引入RouterModule.forRoot方法,其中,appRoutes是路由数组,它定义了具体的路由规则。

  1. import { RouterModule } from '@angular/router';

  2. ......

  3. @NgModule({
  4.     declarations: [......],
  5.     imports: [
  6.         ......,
  7.         RouterModule.forRoot(appRoutes),
  8.     ],
  9.     providers: [],
  10.     bootstrap: [AppComponent]
  11. })
复制代码

2、在壳组件中增加导航条,其中routerLink指令指向路由的目标,routerLinkActive为选中的标签增加css样式

  1. <a routerLink="/home" routerLinkActive="active"></a>
复制代码

3、往壳组件的模板中添加一个router-outlet指令,视图将会被显示在那里

  1. <router-outlet></router-outlet>
复制代码
现在在这个基础上想要实现子路由以及模块的懒加载。

RouterModule.forRoot() 和 RouterModule.forChild()

RouterModule对象提供了两个静态的方法:forRoot()和forChild()来配置路由信息。

RouterModule.forRoot()方法用于在主模块中定义主要的路由信息,RouterModule.forChild()与 Router.forRoot()方法类似,但它只能应用在特性模块中。

即根模块中使用forRoot(),子模块中使用forChild()。

子路由

假设在我们 /settings 设置页面下有 /settings/profile 和 /settings/password 两个页面,分别表示个人资料页和修改密码页。setting作为一个独立的功能块,可以将其封装成一个特性模块。它拥有自己独立的路由,profile和password两个页面的路由可以设置成子路由。

  1. import { NgModule } from '@angular/core';
  2. import { CommonModule } from '@angular/common';
  3. import { Routes, RouterModule } from '@angular/router';

  4. export const ROUTES: Routes = [
  5.   {
  6.     path: '',
  7.     component: SettingsComponent,
  8.     children: [
  9.       { path: 'profile', component: ProfileSettingsComponent },
  10.       { path: 'password', component: PasswordSettingsComponent }
  11.     ]
  12.   }
  13. ];

  14. @NgModule({
  15.   imports: [
  16.     CommonModule,//注意这里引入的CommonModule,它的作用后面会专门讲到,这里不引入的话页面会报错

  17.     RouterModule.forChild(ROUTES)
  18.   ],
  19. })
  20. export class SettingsModule {}
复制代码
在SettingsModule 模块中我们使用forChild()方法,因为SettingsModule不是我们应用的主模块。

另一个主要的区别是我们将 SettingsModule 模块的主路径设置为空路径 ('')。因为如果我们路径设置为 /settings,它将匹配 /settings/settings。通过指定一个空的路径,它就会匹配 /settings 路径。

懒加载:loadChildren

在根模块AppModule中配置setting模块的路由信息:

  1. export const ROUTES: Routes = [
  2.   {
  3.     path: 'settings',
  4.     loadChildren: './settings/settings.module#SettingsModule'
  5.   }
  6. ];

  7. @NgModule({
  8.   imports: [
  9.     BrowserModule,
  10.     RouterModule.forRoot(ROUTES)
  11.   ],
  12.   // ...
  13. })
  14. export class AppModule {}
复制代码
这里使用到了懒加载LoadChildren属性。这里没有将SettingsModule导入到AppModule中,而是通过loadChildren属性,告诉Angular路由依据loadChildren属性配置的路径去加载SettingsModule 模块。这就是模块懒加载功能的具体应用,当用户访问 /settings/** 路径的时候,才会加载对应的 SettingsModule 模块,这减少了应用启动时加载资源的大小。

loadChildren的属性值由三部分组成:

需要导入模块的相对路径

#分隔符

导出模块类的名称

CommonModule模块

之前说到在特性模块中要引入CommonModule模块,我一开始没有注意到要在特性模块中引入,结果在路由的时候页面报错:



core.es5.js:1020 ERROR Error: Uncaught (in promise): Error: Template parse errors:
Can't bind to 'ngClass' since it isn't a known property of 'div'.

Can't bind to 'ngForOf' since it isn't a known property of 'p'.

Property binding ngForOf not used by any directive on an embedded template. Make sure that the property name is spelled correctly and all directives are listed in the "@NgModule.declarations".

Can't bind to 'ngIf' since it isn't a known property of 'div'.

......
类似这种一大堆错误,感觉像是 'ngClass' 'ngFor' 'ngIf'这样的指令都没有定义似的。

检查了好久,发现是因为我在特性模块中没有引入CommonModule,引入之后这些错误就都消失了。

  1. import { CommonModule } from '@angular/common';
  2. @NgModule({
  3.   imports: [
  4.     CommonModule,
  5.     ......
  6.   ],
  7. })
复制代码
CommonModule提供了很多应用程序中常用的指令,包括NgIf和NgFor等。更准确地说,NgIf等指令是来自@angular/common的CommonModule中声明的。

我们在根模块AppModule中导入了BrowserModule模块,BrowserModule导入了CommonModule并且重新导出了它。最终的效果是:只要导入BrowserModule就自动获得了CommonModule中的指令。

导入BrowserModule会让该模块公开的所有组件、指令和管道在AppModule下的任何组件模板中直接可用,而不需要额外的繁琐步骤。但是在其它任何模块中都不要导入BrowserModule。特性模块和惰性加载模块应该改成导入CommonModule。它们不需要重新初始化全应用级的提供商。 如果你在惰性加载模块中导入BrowserModule,Angular就会抛出一个错误。



以上就是我在这两天使用Angular子路由和懒加载中遇到的一些问题和总结。





上一篇:最新Python开发工程师面试指导
下一篇:程序员的十个层次 你属于哪一层?
帖子永久地址: 

架构师_程序员 - 论坛版权1、本主题所有言论和图片纯属会员个人意见,与本论坛立场无关
2、本站所有主题由该帖子作者发表,该帖子作者与架构师_程序员享有帖子相关版权
3、其他单位或个人使用、转载或引用本文时必须同时征得该帖子作者和架构师_程序员的同意
4、帖子作者须承担一切因本文发表而直接或间接导致的民事或刑事法律责任
5、本帖部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责
6、如本帖侵犯到任何版权问题,请立即告知本站,本站将及时予与删除并致以最深的歉意
7、架构师_程序员管理员和版主有权不事先通知发贴者而删除本文

码农网,只发表在实践过程中,遇到的技术难题,不误导他人。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

免责声明:
码农网所发布的一切软件、编程资料或者文章仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。

Mail To:help@itsvse.com

QQ|Archiver|手机版|小黑屋|架构师 ( 鲁ICP备14021824号-2 )|网站地图

GMT+8, 2019-6-16 11:31

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表