Angular实现预加载延迟模块的示例

所属分类: 网络编程 / JavaScript 阅读数: 852
收藏 0 赞 0 分享

在使用路由延迟加载中,我们介绍了如何使用模块来拆分应用,在访问到这个模块的时候, Angular 加载这个模块。但这需要一点时间。在用户第一次点击的时候,会有一点延迟。

我们可以通过预加载路由来修复这个问题。路由可以在用户与其它部分交互的时候,异步加载延迟的模块。这可以使用户在访问延迟模块的时候更快地访问。

本文将在上一个示例的基础上,增加预加载的功能。

在上一节中,我们的根路由定义在 main.routing.ts,我们在 app.module.ts 中使用了根路由定义。

需要注意的是,Home 组件是提前加载的。我们将在系统启动之后渲染这个组件。

在 Angular 渲染 Home 组件之后,用户就可以与应用交互了,我们可以通过简单的配置在后台预加载其它模块。

启用预加载

我们在 forRoot 函数中,提供一个预加载的策略。

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

import { AppComponent } from './app.component';
import { HomeComponent } from './home/home.component';
import { routes } from './main.routing';
import { RouterModule } from '@angular/router';
import { PreloadAllModules } from '@angular/router';

@NgModule({
 declarations: [
  AppComponent,
  HomeComponent
 ],
 imports: [
  BrowserModule,
  RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules })
 ],
 providers: [],
 bootstrap: [AppComponent]
})
export class AppModule { }

这个 PreloadAllModules 策略来自 @angular/router,所以我们还需要导入它。

定制预加载策略

router 包中预定义了两个策略:

  1. 不预加载 NoPreloading
  2. 预加载所有模块 PreloadAllModules

5 秒之后加载模块

但是,您可以自己定义一个定制的策略。这比您想的要更为简单。例如,您希望在应用初始化 5 秒之后加载其余的模块。

您需要实现接口 PreloadingStrategy,我们定义一个 CustomPreloadingStrategy 的自定义策略类。

import { Route } from '@angular/router';
import { PreloadingStrategy } from '@angular/router';
import { Observable } from 'rxjs/Rx';

export class CustomPreloadingStrategy implements PreloadingStrategy {
  preload(route: Route, fn: () => Observable<boolean>): Observable<boolean> {
    return Observable.of(true).delay(5000).flatMap((_: boolean) => fn());
  }
}

然后,修改 app.module.ts 使用这个自定义策略。需要注意的是,您还需要在 prodivers 中添加这个类。以实现依赖注入。

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

import { AppComponent } from './app.component';
import { HomeComponent } from './home/home.component';
import { routes } from './main.routing';
import { RouterModule } from '@angular/router';
import { CustomPreloadingStrategy } from './preload';

@NgModule({
 declarations: [
  AppComponent,
  HomeComponent
 ],
 imports: [
  BrowserModule,
  RouterModule.forRoot(routes, { preloadingStrategy: CustomPreloadingStrategy })
 ],
 providers: [CustomPreloadingStrategy ],
 bootstrap: [AppComponent]
})
export class AppModule { }

你会看到 在 5 秒钟之后,这个功能模块被自动加载了。

加载指定模块

我们还可以在路由中定义附加的参数来指定哪些模块进行预加载,我们使用路由定义中的 data 来提供这个附加的数据。

import { Routes } from '@angular/router';
// HomeComponent this components will be eager loaded
import { HomeComponent } from './home/home.component';

export const routes: Routes = [
  { path: '', component: HomeComponent, pathMatch: 'full' },
  { path: 'shop', loadChildren: './shop/shop.module#ShopModule', data: {preload: true} },
  { path: '**', component: HomeComponent }
];

然后,我们定义新的加载策略。

import { Observable } from 'rxjs/Rx';
import { PreloadingStrategy, Route } from '@angular/router';

export class PreloadSelectedModules implements PreloadingStrategy {
  preload(route: Route, load: Function): Observable<any> {
    return route.data && route.data.preload ? load() : Observable.of(null);
  }
}

最后,在 app.module.ts 中使用这个策略。

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

import { AppComponent } from './app.component';
import { HomeComponent } from './home/home.component';
import { routes } from './main.routing';
import { RouterModule } from '@angular/router';
import { PreloadSelectedModules } from './preload.module';

@NgModule({
 declarations: [
  AppComponent,
  HomeComponent
 ],
 imports: [
  BrowserModule,
  RouterModule.forRoot(routes, { preloadingStrategy: PreloadSelectedModules })
 ],
 providers: [PreloadSelectedModules ],
 bootstrap: [AppComponent]
})
export class AppModule { }



此时,可以看到,模块直接被预加载了。即使您点击链接,也不会再有新的请求发生。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

更多精彩内容其他人还在看

jQuery 行级解析读取XML文件(附源码)

项目中应用jQuery解析读取XML语言配置文件来实现语言的调度。这是jQuery解析读取XML文件功能的测试源码,现拿出来分享。
收藏 0 赞 0 分享

JS 文件本身编码转换 图文教程

JS编码转换,这句话本身就是一句具有二重义的话。通常理解为JS文件里能转换编码的代码,但是,我所碰到的问题并不是这样的,是要解决JS文件本身的编码问题,它是UTF-8编码的还是ANSI编码的?
收藏 0 赞 0 分享

jQuery Ajax之$.get()方法和$.post()方法

load()方法通常用来从Web服务器上获取静态的数据文件,然而这并不能体现Ajax的全部价值。在项目中,如果需要传递一些参数给服务器中的页面,那么可以使用$.get()或者$.post()方法(或者是后面要讲解到的$.ajax方法)。
收藏 0 赞 0 分享

jQuery Ajax之load()方法

jQuery对Ajax操作进行了封装,在jQuery中$.ajax()方法属于最底层的方法,第2层是laod()、$.get()和$.post()方法,第3层是$.getScript()和$.getJSON()方法。
收藏 0 赞 0 分享

JavaScript 核心参考教程 内置对象

JavaScript 是根据 "ECMAScript"标准制定的网页脚本语言。这个标准由 ECMA 组织发展和维护。ECMA-262 是正式的 JavaScript 标准。
收藏 0 赞 0 分享

JavaScript 核心参考教程 RegExp对象

JavaScript 核心参考教程RegExp对象,学习正则表达式的朋友可以参考下。
收藏 0 赞 0 分享

javascript hashtable实现代码

javascript中没有像c#,java那样的哈希表(hashtable), 然而,javascript中的Array也只有一些类似于'哈希表'的非常简单功能。
收藏 0 赞 0 分享

百度留言本js 大家可以参考下

百度留言本js 大家可以参考下。
收藏 0 赞 0 分享

javascript 判断某年某月有多少天的实现代码 推荐

以前写网页的时候,经常碰到选择日期的问题,其实就是判断某年某月有多少天。
收藏 0 赞 0 分享

让iframe子窗体取父窗体地址栏参数(querystring)

突然用到,记录一下,对地址栏字符串用正则处理最好,有时间研究一下。 主要是思路。
收藏 0 赞 0 分享
查看更多