前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >模块化开发 Angular 应用 [含懒加载]

模块化开发 Angular 应用 [含懒加载]

作者头像
Jimmy_is_jimmy
发布2022-09-19 16:55:57
3K0
发布2022-09-19 16:55:57
举报
文章被收录于专栏:call_me_Rcall_me_R

想要更好地理解 Angular 应用程序所有的不同构建的模块?

在这篇文章中,我们将走进模块的内容。

angular 应用中,模块是共享和重用代码的好方法。

共享模块不仅让你的应用联系紧密,而且可以对你的应用进行瘦身。

在这个教程中,我们将创建自定义的模块,并发掘它的组件。

然后,我们将学习怎么使用我们的模块来启用延迟加载,从而使应用更小,使用户体验更好。

我们开始吧!

angular-convention.webp
angular-convention.webp

App Module

Angular 里面,一切皆可组织成模块。所以,即使你不知道哪些是模块或者怎么使用它们,你已经无行在应用中使用它们了。其中最突出的是 AppModule

AppModule 是你应用中的根模块,并且对于运行我们的应用程序是必要的模块。在这里,我们可以定义应用程序使用哪些组件或者哪些模块。那么它长什么样呢?我们通过 angular-cli 来生成一个基本的 AppModule

代码语言:javascript
复制
// src/app/app.module.ts

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

import { AppComponent } from './app.component'

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule],
  providers: [],
  bootstrap: [AppComponent],
})
export class AppModule {}
复制代码

要生成你自己的模块,请打开终端并进入项目的根目录。

使用下面的命令行去生成一个新的模块文件。

代码语言:javascript
复制
ng generate module [name]
复制代码
angular-question.webp
angular-question.webp

一个 Angular Module 是什么?

简单来说,一个模块就是一个类,就像组件和服务一样。

Angular 中的代码通常以模块的形式组织。我们可以将模块视为包含特定用例所需要代码的包或捆绑包。

最重要的模块是 App-Module,每个通过脚手架生成的应用都有它。

但是,App-Module 很可能不是你目前为止遇到的唯一模块。还有很多开箱即用的模块。

比如 Http-Client-Module,它包含一个很有用处的 Http-ClientForms-Module(其中包含 UI 组件和 HTML-Forms 指令)。

正如我们上面的例子中看到的,我们要使用模块之前,需要先导入模块。

App-Module 是应用程序的根模块。该模块导入其他模块,这些模块可以自己导入其他模块。

就像组件一样,生成的结构是一个模块树。

angular-code-banner.webp
angular-code-banner.webp

@NgModule

@NgModule 操作符里面,我们定义模块的所有属性。我们提供了一个简单的 JavaScript 对象作为参数。让我们仔细点看,这些属性是什么,又干了些什么:

Bootstrap

定义应用程序的根组件。仅在 AppModule 中使用它。

Exports

我们在这里定义要组件、指令或者管道。这意味着,我们的模块在导入时将这些模块提供给其他模块。否则,这些模块将停留在模块内部,无法从外部访问。

Declarations

declarations 数组中,我们定义着所有的组件,指令和管道,我们可以在这个模块内使用。如果一个组件(或者指令或者管道)你并没有添加到 declarations 中,但是你又在模块或者应用中使用了,angular 应用在运行时报错。此外,一个组件只能在一个模块中声明。如果你想在多个模块中使用你的组件,你需要将改组件捆绑到一个单独的模块中,并将其导入到模块中

Imports

说到导入... 你的模块可以导入任意数量的子模块。还没有定义任何自定义模块?没问题,我们将解决这个问题。即使你没有任何模块,你仍然需要导入一些 angular 模块。正如我们之前提到的,Angular 在构建之初已经考虑到了模块化。虽然很多特性都包含在 Angular 的核心中,但是有些特性被捆绑在它们自己的模块中。比如,你想使用 HttpClient,你得想导入 HttpClientModule

Providers

我们定义了模块所需的任何的 @Injectables。然后,任何子组件或者模块都可以通过依赖注入获得该 @Injectables 相同的实例。在 AppModule 案例中,这些 @Injectables 就是 application-scoped

构建自定义模块

我们假装已经构建了一个很棒的应用程序。这个程序只有一个模块,就是 AppModule

现在,为我们应用程序添加登录内容。登录内容将包含一个登录的页面和一个注册的页面。也许会有一个帮助的页面。每个页面都是以组件的方式呈现。

代码语言:javascript
复制
LoginComponent
RegisterComponent
HelpComponent
复制代码

同时,我们需要一个服务发起 Http 请求。

代码语言:javascript
复制
AuthenticationService
复制代码

由于这些页面是完全独立的,并且与我们应用程序的内容页面无关。我们决定将它们捆绑到一个单独的模块中。我们称这个模块为 AuthentictionModule

代码语言:javascript
复制
// src/app/authentication/authentication.module.ts

import { NgModule } from '@angular/core'
import { CommonModule } from '@angular/common'

@NgModule({
  imports: [CommonModule],
})
export class AuthenticationModule {}
复制代码

现在,将我们的组件添加到 declarations 部分。同时,我们将它们放在 exports 部分,因为我们想在模块外部使用它们。

代码语言:javascript
复制
// src/app/authentication/authentication.module.ts

import { HelpComponent } from './help/help.component'
import { RegisterComponent } from './register/register.component'
import { LoginComponent } from './login/login.component'
import { NgModule } from '@angular/core'
import { CommonModule } from '@angular/common'

@NgModule({
  imports: [CommonModule],
  declarations: [LoginComponent, RegisterComponent, HelpComponent],
  exports: [LoginComponent, RegisterComponent, HelpComponent],
})
export class AuthenticationModule {}
复制代码

已经准备好了。现在,我们可以在 AppModule 导入它,然后使用它里面的组件,比如在 AppComponent 中使用。

代码语言:javascript
复制
// src/app/app.module.ts

import { AuthenticationModule } from './authentication/authentication.module'
import { BrowserModule } from '@angular/platform-browser'
import { NgModule } from '@angular/core'

import { AppComponent } from './app.component'

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule, AuthenticationModule],
  providers: [],
  bootstrap: [AppComponent],
})
export class AppModule {}
复制代码
angular-lazy-loading.webp
angular-lazy-loading.webp

Lazy-Loading Modules

事实表明,你可以使用模块做更多事情,而不是仅仅组织你的组件。也可以延迟加载模块。这是什么意思呢?

Angular 程序的下载体积很大。根据你的用户场景,这是一个很大的问题。特别是在移动端,加载一个应用程序可能需要耗费很长时间。减少加载时间的一种方法是将应用程序拆分成模块。

当你以惰性方式加载模块时,它不会包含在初始的程序中。相反,它仅在需要的时候才下载。为啥要下载我们还没用得上的组件呢,是吧?

那么,它是怎么工作的?

我们用惰性加载方式更改下先前的例子。为了实现这点,我们要在应用中添加路由。

首先,我们用路由配置来配置路由模块。所以,我们创建一个名为 app.routing.ts 的文件,它跟 app.module 同级。

代码语言:javascript
复制
// src/app/app.routing.ts

import { ContentComponent } from './content/content.component'
import { Routes, RouterModule } from '@angular/router'
import { ModuleWithProviders } from '@angular/core'

export const routes: Routes = [
  { path: '', pathMatch: 'full', redirectTo: 'content' },
  { path: 'content', component: ContentComponent },
  {
    path: 'login',
    loadChildren: './authentication/authentication.module#AuthenticationModule',
  },
]

export const routing: ModuleWithProviders = RouterModule.forRoot(routes)
复制代码

非延迟加载的组件由路径和组件属性指定。如果我们想在特定的路由上延迟加载模块,我们可以使用 loadChildren 属性。这里我们指定模块的路径和名称,用 # 分隔开。

之后,我们可以在我们的 AppModule 中导入配置模块。我们还删除了 AuthenticationModule 的导入,因为它是延迟加载的。

代码语言:javascript
复制
// src/app/app.module.ts

import { routing } from './app.routing'
import { BrowserModule } from '@angular/platform-browser'
import { NgModule } from '@angular/core'

import { AppComponent } from './app.component'
import { ContentComponent } from './content/content.component'

@NgModule({
  declarations: [AppComponent, ContentComponent],
  imports: [
    BrowserModule,
    routing, //import routing
  ],
  providers: [],
  bootstrap: [AppComponent],
})
export class AppModule {}
复制代码

接着,我们在程序的某个地方添加 router-outlet。这里我们把它放在 AppComponent 中。

代码语言:javascript
复制
<!-- src/app/app.component.html -->

<router-outlet></router-outlet>
复制代码

如果我们进入那个路由,那个模块将被加载。但是此时屏幕上什么都没有。因为 Angular 还不知道现实哪个组件。为了解决这个问题,我们必须为 authentication module 定义子路由。这看起来集合和 app.routing 完全一样。不一样的是,我们调用的是 forChild() 而不是 forRoot(),当然,路由也不同。

代码语言:javascript
复制
// src/app/authentication/authentication.routing.ts

import { AuthenticationComponent } from './authentication.component'
import { HelpComponent } from './help/help.component'
import { RegisterComponent } from './register/register.component'
import { LoginComponent } from './login/login.component'
import { Routes, RouterModule } from '@angular/router'
import { ModuleWithProviders } from '@angular/core'

export const routes: Routes = [
  { path: '', component: LoginComponent }, // default route of the module
  { path: 'login', component: LoginComponent },
  { path: 'register', component: RegisterComponent },
  { path: 'help', component: HelpComponent },
]

export const routing: ModuleWithProviders = RouterModule.forChild(routes)
复制代码

现在需要做的是,将路由导入到 AuthenticationModule 中。当我们再次进入路由后,登陆组件会被展示出来。这是因为我们配置其为默认路由。

代码语言:javascript
复制
// src/app/authentication/authentication.module.ts

import { AuthenticationComponent } from './authentication.component'
import { routing } from './authentication.routing'
import { HelpComponent } from './help/help.component'
import { RegisterComponent } from './register/register.component'
import { LoginComponent } from './login/login.component'
import { NgModule } from '@angular/core'
import { CommonModule } from '@angular/common'

@NgModule({
  imports: [
    CommonModule,
    routing, // import routing
  ],
  declarations: [
    AuthenticationComponent,
    LoginComponent,
    RegisterComponent,
    HelpComponent,
  ],
})
export class AuthenticationModule {}
复制代码
angular-error-banner.webp
angular-error-banner.webp

Angular 模块不是 JavaScript 模块

别把 Angular 模块和 JavaScript 模块混淆。Angular 模块是类,用 @NgModule 进行标识。另一方面,当我们使用 Typescript 关键字 import 导入模块时,我们在导入一个 JavaScript 模块。该模块可以包含 Angular 模块。

Angular 模块
代码语言:javascript
复制
// src/app/app.module.ts

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule],
  providers: [],
  bootstrap: [AppComponent],
})
export class AppModule {}
复制代码
JavaScript 模块
代码语言:javascript
复制
import { BrowserModule } from '@angular/platform-browser'
import { NgModule } from '@angular/core'
复制代码

本文是译文,采用的是意译的方式,其中加上个人的理解和注释,原文地址是:malcoded.com/posts/angul…

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-07-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • App Module
  • 一个 Angular Module 是什么?
  • @NgModule
    • Bootstrap
      • Exports
        • Declarations
          • Imports
            • Providers
            • 构建自定义模块
            • Lazy-Loading Modules
              • 那么,它是怎么工作的?
              • Angular 模块不是 JavaScript 模块
                • Angular 模块
                  • JavaScript 模块
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档