[Angular2] Angular 2中NgModule,Lazy Loading与Route

原创
2016/09/01 23:12
阅读数 2.8K

更新至Angular 2.0正式版,router 3.0

就在我写这篇博客的时候,Angular2官方已经发布了RC 6,angular-router模块发布了RC 2.这次更新主要就是把废除的属性进行了移除跟代码重构,跟RC5相比并没有太大的变化,所以今天我们依旧用RC5来讲解,稍后我会统一把代码升级到RC 6.

Angular的主打就是单页应用(SPA),而且当我们的应用打成一个文件后体积在可承受范围之内时,我们并不需要做懒加载,这对一些中小型应用来说也是最佳选择,毕竟只需要一次加载就可以享受native的体验还是很高大上的。然而,当我们构建大型应用的时候,不得不考虑加载速度的问题,这个时候如果我们可以把某些可以拆分的模块单独打包,只有需要的时候再去加载,Lazy loading就显得格外重要了。

今天我们简单的讲一下在angular 2中怎么来做Lazy Loading,希望可以给大家一些启发或者帮助。

目录变化

老规矩我们先来看看这次跟上次的演示相比([Angular2] 添加Angular 2 router(路由)配置信息)我们项目的目录变动情况

这次的变化主要是我们把about封装成了模块(module),并且新建了一个叫blog的模块。细看名字还不一样,about文件夹前面有个+号??这代表这个模块是Lazy Loading的~哈哈~我们这里引入blog模块就是为了让大家跟好的看到lazy loading与直接加载的区别。

每个Module都单独有一个自己的routing文件,是专门负责这个模块的route的,这样就不会跟root app的routing混杂在一起了。

Blog 模块

因为blog module是在应用启动时直接下载下来的,所以我们先来看一下它吧。首先我们得 先来回顾一下我们在第二篇里([Angular2]创建简单的Angular 2 NgModule与Components)讲到关于module的理论,自行脑补下图~~

我们的Blog module就是一个简单的feature module,然后需要有自己的routing文件,大体就像下面这样:

import { NgModule } from '@angular/core';

import { BlogComponent }   from './blog.component';
import { routing } from './blog.routing';

@NgModule({
    imports: [routing], /**  导入我们blog module自己routing */
    declarations: [BlogComponent]/** 必须要声明这个module中要用到的component,directives,pipes */
})
export class BlogModule { }


/**
* 创建blog自己的routing文件
*/
import { Routes, RouterModule } from '@angular/router';

import { BlogComponent } from './blog.component';

const routes: Routes = [
  { path: 'blog', component: BlogComponent }/** 配置blog url的导航信息*/
];

export const routing = RouterModule.forChild(routes);

然后就想上图的模型中 一样,我们需要把blog module导入到app module中

app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule  } from '@angular/platform-browser';

import { BlogModule } from './blog/blog.module';

import AppComponent from './common/components/app.component';
import { HomeComponent } from './common/components/index';
import { routing } from './common/router/app.routing';

@NgModule({
    imports: [
        BrowserModule,
        BlogModule, /** 导入我们的Blog模块 */
        routing,
    ],
    declarations: [AppComponent, HomeComponent],
    bootstrap: [AppComponent],
})

export class AppModule { }

再来看看app.routing.ts:

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

import { HomeComponent } from '../components/index';

const routes: Routes = [
    { path: '', component: HomeComponent },
    { path: 'about', loadChildren: 'app/+about/about.module' } /** loadChildren??这是什么鬼?? */
];

export const routing = RouterModule.forRoot(routes);

这时候你会发现app的routing文件中并没有blog模块的链接信息??这是因为我们上面在blog模块自己routing文件中已经配置过了,而我们又把blog模块引入了app module, 所以当我们的应用启动时,不仅直接下载了blog模块的代码,blog模块的导航信息也会合并到app的主配置信息里,这样我们的应用就知道当我们点击blog按钮是应该显示哪个模块了~~

+About 模块

这里我们把之前写好的about component分离出来封装成了module,并且我们用它来演示Lazy Loading的过程。

跟Blog模块一样我们先来看一下about module的代码:

import { NgModule } from '@angular/core';

import { AboutComponent }   from './about.component';
import { routing } from './about.routing';

@NgModule({
    imports: [routing],
    declarations: [AboutComponent]
})
export default class AboutModule { }


/**
* 引入routing文件
*/

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

import { AboutComponent } from './about.component';

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

export const routing = RouterModule.forChild(routes);

看完这段代码发现其实跟Blog模块没啥区别啊??是的,没有错,确实没什么区别,除了!!我们的routing信息写了一个空的path,而不是about,为什么呢?这是因为我们上面的app.routing.ts中已经定义了about了啊,也就是这一行

{ path: 'about', loadChildren: 'app/+about/about.module' }

loadChilden又是神马??这就是lazy loading的关键所在了~loadChildren底层是调用了NgModuleFactoryLoader的load()方法来做的,但是这只是一个抽象类,并没有实现方法啊!!怎么做到lazy loading的!!!少年,淡定~~

如果你去查过官方的API文档你会发现,其实它还有另一个类叫SystemJsNgModuleLoader, 这又是个神马,点进去看看,原来这就是NgModuleFactoryLoader的实现类!那为什么叫SystemJsNgModuleLoader呢,难道跟systemJS有关??少年,你知道的太多了,哈哈~~没错,它的底层就是用的systemJS去加载的loadChildren中我们所写的路径,就跟我们在第一篇中配置的sysytem的信息去加载angular2的包一样一样的~~是不是瞬间觉得其实Lazy Loading看上去高大上,其实很简单的啊~~~哈哈哈

需要注意的就是,这里的loadChildren其实不止是string类型,还可以是function或者type类型。这里就留给大家自己去探索吧。

结语

这里我们只是介绍了一下普通的module与Lazy Loading module在实际应用中的简单使用,并没有深入写很多复杂的route之类。因为Router其实是很大的一块,这也是问什么它在angular 2中是单独的一个模块,如果有机会的话,我会写一篇专门关于复杂router以及auth相关的文章。

最后,老规矩~~看一下我们的战利品~~

当我们点击About的时候,我们才去加载了跟About有关的代码:

 

文章中的代码已经整理上传到GitHub: https://github.com/WuKongW/Angular2_POC

 

展开阅读全文
打赏
2
7 收藏
分享
加载中
更多评论
打赏
0 评论
7 收藏
2
分享
返回顶部
顶部