如何在Angular 12中偷懒加载组件
构建大型应用程序对应用程序的路由加载时间有很大影响。随着应用程序的增长,其在浏览器上的性能会大大降低,并降低用户体验。
在本教程中,我将带领你了解Angular中懒惰加载的概念,以及它如何改善应用程序在浏览器上的加载时间。
前提条件
要继续学习本教程,你需要以下条件。
- 在本地安装Angular CLI。
- 对Angular2+有一些基本了解。
- 具备JavaScript/TypeScript的基本知识。
教学目的
本教程旨在教授你关于懒惰加载的所有知识,这一概念将改变你在Angular中广泛的应用的编码技术。
什么是懒惰加载?
懒加载是一种编程技术,用于提高应用程序的性能,特别是网页,并减少其加载时间。它使网页最初的加载速度更快,而当用户需要时才下载额外的文件。
这是一种在Angular应用程序中加载组件的异步方式。需要的组件被加载到浏览器中,而那些没有被访问过的路由则保持不被加载。
使用懒惰加载的最重要原因是为了改善应用程序的总体加载时间。因此,它在大型应用程序中的使用是必不可少的,如具有大量产品列表的电子商务应用程序。
组件被加载一次也是至关重要的,所以当用户访问一个特定的懒惰加载路线时,当用户下次访问时,该组件将随时可用,因此有了单页应用(SPA)的概念。
设置项目
现在我们已经对为什么需要懒惰加载我们的应用程序有了一个更好的概念,现在我们可以通过运行以下命令来继续并设置我们的项目。
ng new lazyLoadingExample
上面的命令,ng new lazyLoadingExample ,安装我们的Angular应用程序。重要的是要记住,这些命令只有在你安装了Angular CLI(全局/到一个特定的目录)后才能使用。
现在我们的应用程序已经准备好了,让我们继续前进,设置我们的政府项目与不同部门。
我们的项目将有三个模块,AuthModule 、GovernmentModule 、GovernmentFormsModule 。主要目的是根据用户激活的路线,在不同时间加载这三个模块。
让我们通过运行以下命令来设置我们的三个模块。
cd lazyLoadingExample
ng g module auth --routing
ng g module government --routing
ng g module government-forms --routing
上面的命令设置了之前讨论的三个模块,每个模块都有一个路由模块来设置我们的路由。
接下来,在auth 目录中添加两个组件,如下图所示。
ng g c auth/register
ng g c auth/login
当上面的命令被执行后,RegisterComponent 和LoginComponent 组件被添加到AuthModule 。
让我们按照上述步骤,为政府模块添加组件,如下图所示。
# add ministries and governor office components
ng g c government/ministry
ng g c government/governor
#add forms to book and contact government officials
ng g c governor-forms/contact-official
ng g c governor-forms/book-appointment
设置共享组件
在上一节中,我们设置了我们的项目组件和模块。我们还添加了路由模块,我们将编辑这些模块以帮助我们实现懒惰加载。
在这一节中,我们建立一个可重用的组件布局,以帮助我们共享应用程序的标准功能。
在大多数情况下,你需要在一个给定的布局中设置这些路由。例如,登录/注册表单可能只有输入而没有导航条或页脚,这与其他组件不同。
让我们继续,在一个shared 模块内设置两个布局组件,如下图所示。
首先,在app 目录下创建一个共享模块。
ng g module shared
接下来,运行以下命令来添加布局组件。
ng g c shared/main-layout
ng g c shared/auth-layout
现在我们有了我们的布局模块和组件,编辑主布局组件,如下所示。
<!--/app/shared/MainLayoutComponent -->
<div class="top-row">
<div class="top-bar-content">
<div class="row">
<!--col-1--->
<div class="col-md-4">
<div class="logo-top">
<a class="text-decoration-none" [routerLink]="['/']">
<img src="assets/images/top-logo.png" alt=""></a>
</div>
</div>
<!--col-2--->
<div class="col-md-4">
<div class="social-top text-center"> <a href="#"><i class="fab fa-facebook-f"></i></a>
<a href="#"><i class="fab fa-twitter"></i></a>
<a href="#"><i class="fab fa-instagram"></i></a>
</div>
</div>
<!--col-3--->
<div class="col-md-4 text-right">
<div class="top-right-bar text-end">
<a *ngIf="currentUser!=null" class="btntop">Logged in as {{currentUser.name}}</a>
<a *ngIf="!currentUser" class="btntop " [routerLink]="['/auth/login']">Sign In</a>
<a *ngIf="!currentUser" class="btntop" [routerLink]="['/auth/registe']">Register</a>
<button *ngIf="currentUser!=null" class="btntop btn btn-link" (click)="logout()">Sign Out</button>
</div>
</div>
</div>
</div>
</div>
<div class="middle-header">
<div class="top-bar-content">
<div class="row">
<div class="col-md-4"></div>
<div class="col-md-4 text-center">
<div class="logo">
<a class="" routerLink="/"><img src="assets/images/update-logo.png" width="250" height="56" alt="logo"></a>
</div>
</div>
<div class="col-md-4 text-right">
<div class="text-end bar-middle-right">
<ul>
<li><a href="#"><i class="far fa-bell"></i></a>
</li>
<li><a href="#"><i class="fas fa-search"></i></a>
</li>
<li><a class="toggle-bar" id="topbarToggle" href="#"><img src="assets/images/menu-icon.png" alt=""></a>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<div class="marquee">
<marquee class="text-white p-2 font-weight-bolder">
some texts goes here....
</marquee>
</div>
<router-outlet></router-outlet>
<footer>
<div class="footer-contents">
<div class="row">
<div class="col-md-2 content footer-logos">
<a class="btn btn-link" [routerLink]="['/']">
<img class="logos" src="assets/images/new-logo.png" alt="logo">
<img class="social" src="assets/images/logo-underline.png" alt="logo">
</a>
<div class="social-media-links">
<ul class="list-group list-group-horizontal">
<li class="list-group-item bg-transparent border-0"><img src="assets/images/facebook.png" alt="fb"> </li>
<li class="list-group-item bg-transparent border-0"><img src="assets/images/twitter.png" alt="fb"> </li>
<li class="list-group-item bg-transparent border-0"><img src="assets/images/instagram.png" alt="fb"> </li>
</ul>
</div>
</div>
<div class="col-md-5 content">
<h3 class="footer-link quick-links text-center">Quick Links</h3>
<div class="row">
<div class="col-md-6">
<ul class="list-unstyled"></ul>
<li class="list-item"><a [routerLink]="['Link']" class="text-decoration-none">Link2</a></li>
<li class="list-item"><a [routerLink]="['/Link']" class="text-decoration-none">Link2</a></li>
<li class="list-item"><a [routerLink]="['Link']" class="text-decoration-none">Link2</a></li>
<li class="list-item"><a [routerLink]="['Link']" class="text-decoration-none">Link2</a></li>
<li class="list-item"><a [routerLink]="['Link']" class="text-decoration-none">Link2</a></li>
</ul>
</div>
</div>
</div>
<div class="col-md-2 content">
<h3 class="footer-link contact-us">Contact Us</h3>
<div class="contact-us-lists">
<h4 class="call-us">Call Now</h4>
<ul class="list-unstyled">
<li class="list-item"><a class="text-decoration-none">+284xxxx</a></li>
<li class="list-item"><a class="text-decoration-none">+264xxxx</a></li>
</ul>
<h4 class="call-us">Email Address</h4>
<ul class="list-unstyled">
<li class="list-item"><a class="text-decoration-none">info@test.com</a></li>
<li class="list-item"><a class="text-decoration-none">test@test.com</a></li>
</ul>
</div>
</div>
</div>
<div class="divider text-center">
<hr/>
</div>
<div class="row footer-contents-bottom">
<div class="col-md-6 copyright">
<h3>COPYRIGHT 2021, ALL RIGHTS RESERVED</h3>
</div>
<div class="col-md-6 banner">
<h3>Some footer</h3>
</div>
</div>
</div>
</footer>
上面的模板有3个主要部分,标题、主体和页脚。标题部分有认证逻辑,检查当前访问用户是否经过认证。
<a *ngIf="currentUser!=null" class="btntop">Logged in as {{currentUser.name}}</a>
上面的条件检查currentUser 对象是否为空或有一个值。值得注意的是,这个currentUser 对象被存储在浏览器的本地存储中。
然后我们有一个退出按钮,只有在访问用户已经通过认证的情况下,才会让他们看到这个按钮,如下面的条件所示。
<button *ngIf="currentUser!=null" class="btntop btn btn-link" (click)="logout()">Sign Out</button>
在页眉之后,我们有<router-outlet></router-outlet> 元素。router-outlet 是一个指令,可以从@angular/router包中获得,并被路由器用来标记在一个模板中,一个匹配的组件应该被插入。
我们只在页脚定义了关于我们应用程序的基本信息,你可以根据自己的要求进行定制。
接下来,按照上面的概念来定义你的auth布局吧
设置懒惰路线
现在我们有了布局,让我们继续进行,设置认证路由,如下图所示(本节假设你在前面的区域设置了auth布局)。
...
const routes: Routes = [
{
path: '',
component: AuthLayoutComponent,
children: [
{
path: 'register',
component: RegisterComponent,
},
{
path: 'login',
component: LoginComponent,
},
]
}
];
@NgModule({
...
})
export class AuthRoutingModule{ }
上面设置的模块有两个路由,register 和login ,每个都有各自的组件。这些路由被定义为我们之前创建的AuthLayoutComponent 组件的子节点。
接下来,将这个AuthRoutingModule 模块导入主模块,如下图所示。
...
const routes: Routes = [
{
path:'auth',
loadChildren: () => import('./auth/auth.module').then(mod=>mod.AuthModule)
},
];
@NgModule({
...
})
...
上面的模块定义了路径,在这种情况下是auth ,现在我们不是设置组件,而是加载AuthModule ,它已经有了组件。
结果认证的完整路径是。
/auth/register
/auth/login
你会注意到,该路径结合了主路径auth 和子组件register 和login 。
这些概念仍然是相同的,你可以按照上述程序为government 和government forms 设置其他的懒惰加载路径。
总结
在本教程中,我们已经讨论了Angular懒惰加载的概念。你已经看到了我们如何使用这个概念,只加载那些路由已经被用户激活的组件。
除了它的路由模块,组件不得在其他地方被引用。因此,我们需要从app-module.ts 文件中删除该组件的引用;否则,它将被急切地加载。所有的子路由必须堆叠在一起,并且有相同的路由前缀。
懒惰加载是使你的SPA精简的好方法,也意味着通过一些小的改变来加快加载时间。这些增强了用户体验,并将为你的终端用户带来所有的不同!