2021年的Angular最佳实践

目录

使用Angular CLI

保持最新

严格模式

使用延迟加载

取消订阅RxJS Observables

将ngFor与trackBy一起使用

结论


AngularGoogle开发人员使用TypeScript构建,是一个开源JavaScript框架,旨在构建前端应用程序。

Angular 2+Angular.js的继承者,使用TypeScript而不是JavaScript从头开始​​重写,这有助于避免许多与JavaScript相关的问题,并确保遵循最佳实践以及与IDE的集成,这要归功于静态类型和TypeScript中基于类的面向对象特性。

Angular不仅仅是一个框架,而是一个完整的平台,其中包含使前端Web和移动开发更易于管理的功能。此外,由于社区的项目,您可以为移动(IonicNativeScript)和桌面(Electron)设备构建本机应用程序。

Angular与其他现代JavaScript库(例如ReactVue.js)一样,使用了许多共享概念。React在全球Web开发人员中更受欢迎,而Angular则适用于企业应用程序。

本文介绍了开发人员在构建Angular应用程序时应遵循的一些最佳实践。它还探讨了Wijmo(来自GrapeCity100多个JavaScript UI组件的动态集合)如何使开发人员能够使用Angular框架构建尖端的网格、图表等。

使用Angular CLI

在开发Web应用程序时,您应该首先考虑的是开发工具。如今,我们拥有现代工具,使前端Web开发变得更加简单。对于Angular,我们有很多工具,最重要的是官方的Angular CLINx,一个智能且可扩展的构建框架。

尽管您可以 在不使用官方CLI的情况下创建Angular项目,但这仅对学习有用。对于实际开发,您应该使用 Angular CLI。它是由Angular背后的官方团队在Node.js之上创建的命令行界面。它使得从一开始就初始化一个完全可用的Angular应用程序变得非常容易,而无需配置像Webpack这样的构建工具。它通过提供脚手架结构(例如模块和组件)、测试(单元、集成和e2e测试)、构建最终生产包,甚至帮助您部署最终应用程序的命令,在开发过程中提供帮助。

确保使用Angular CLI生成您的项目,因为它带有团队推荐的最佳实践,如果您正在构建全栈应用程序,甚至可以使用Nx

在安装Angular CLI之前,您必须安装最新版本的Node.jsnpm。如果没有,您可以使用以下方法之一:

  • 官方网站下载适用于您的操作系统的安装程序 
  • 为您的目标系统使用官方包管理器
  • 使用NVMNode版本管理工具 ,使您能够管理 系统上的多个Node版本。在您的机器上全局安装软件包也很有帮助,而无需在LinuxMAC上使用sudo并且无需额外配置

现在,使用以下命令安装Angular CLI

npm install -g @angular/cli

此命令会在您的系统上全局安装CLI

您可以运行ng命令来获取您可以使用的所有可用命令,然后运行​​ng后跟特定命令和--help选项以显示该命令的帮助文件。

您可以使用以下命令检查已安装的版本:

ng version

接下来,运行以下命令以生成一个新项目:

ng new angular-practices-demo

Angular会问你:

  • 您想添加Angular路由吗?输入“y”
  • 您想使用哪种样式表格式?使用箭头键选择SCSS

使用可扩展和可维护的项目结构

如果您之前做过Web开发,您就会知道在第一次尝试时找到一个方便的项目结构或架构并不总是那么容易。不过,随着您在构建小型和大型应用程序方面获得更多经验,它会变得更容易。

对于小型应用程序,Angular CLI生成的默认结构是可以的。尽管如此,一旦您的项目增长,您会发现正确维护和扩展您的应用程序具有挑战性。

这是一篇关于如何构建应用程序文件夹的优秀文章 ,您可以从一个准系统的Angular项目开始,然后移动到具有单独组件和页面文件夹的更有条理的实体文件夹结构。页面只是一个路由组件。

此外,要遵循的一个好做法是使用核心模块、共享模块和每个应用程序功能的功能模块(以及引导应用程序的根应用程序模块)构建您的应用程序。然后将app模块中的导入移动到核心模块,并将app模块仅用于应用程序引导。

您必须将所有单例服务放置在核心模块中,整个应用程序只有一个实例。例如,对于每个应用程序,身份验证服务应该只有一个实例作为核心模块的一部分。

在共享模块中,您应该放置在多个模块中使用的公共工件(组件、指令、管道等),以便您可以导入共享模块以使用它们。对于不注入服务但只能通过props接收数据的dumb组件和管道,共享模块也是一个好地方 

假设您正在使用来自GrapeCity的WijmoUI组件库 。在这种情况下,这是导入和重新导出您打算在整个应用程序中使用的组件的绝佳位置,因此您无需在每个模块中重复导入。

要继续我们之前生成的项目,请运行以下命令来创建核心和共享模块:

ng generate module core

ng generate module shared

接下来,假设我们需要产品和购物车的两个特征。

使用相同的命令为它们生成两个功能模块:

ng generate module product

ng generate module cart

接下来,打开src/app/shared.module.ts文件并更新如下:

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

import { CommonModule } from '@angular/common';

import { FormsModule } from '@angular/forms';

@NgModule({

    declarations: [],

imports: [

    CommonModule

],

exports: [

    CommonModule,

    FormsModule

]

})

export class SharedModule { }

在这里,我们将FormsModule添加到exports数组中,因此该数组将其导出到其他导入共享模块的模块,但我们没有将其添加到imports数组中。这样,我们就可以让其他模块访问FormsModule,而无需直接将导入共享的 NgModule中。

接下来,我们重新导出 CommonModule  FormsModule ,以使用CommonModule中的NgIf NgFor这样的常用指令,并将组件属性绑定到导入这个SharedModule的模块中的[(ngModel)]

接下来,打开src/app/app.module.ts文件并导入核心和共享模块,如下所示:

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

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

import { AppRoutingModule } from './app-routing.module';

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

import { CoreModule } from './core/core.module';

import { SharedModule } from './shared/shared.module';

@NgModule({

    declarations: [

        AppComponent

],

imports: [

    BrowserModule,

    AppRoutingModule,

    CoreModule,

    SharedModule

],

providers: [],

bootstrap: [AppComponent]

})

export class AppModule { }

此外,从ProductModule  CartModule删除 CommonModule,并导入SharedModule ,因为它已经导出了 CommonModule.

保持最新

Angular遵循语义版本控制,每六个月发布一个新的主要版本。

语义版本控制是用于软件版本控制的约定。它有一个major.minor.patch格式。当发布主要、次要或补丁更改时,Angular会增加每个部分。

您可以从CHANGELOG关注有关Angular最新版本的新闻  ,并确保您的Angular版本保持最新,确保您始终获得最新的功能、错误修复和性能增强,如Ivy

如果您在将项目从一个版本更新到下一个版本时也使用了这个官方工具,那将会有所帮助 

严格模式

我们在介绍中提到,Angular 2+从早期阶段就采用了TypeScript,确保平台(包括框架和工具)遵循最佳实践,例如依赖注入,这使得测试更易于管理和性能预算。

Angular团队已经通过Angular 10中的一个选项逐步应用严格模式,默认情况下为从Angular 12开始的所有项目启用严格模式。这是现在默认启用的最佳实践,但如果您出于学习目的必须禁用它, 在创建新项目时使用--no-strict选项。

对于现有项目,您可以在tsconfig.json中启用严格模式,如下所示:

{
  "compilerOptions": {
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
  },
  "angularCompilerOptions": {
    "enableI18nLegacyMessageIdFormat": false,
    "strictInjectionParameters": true,
    "strictInputAccessModifiers": true,
    "strictTemplates": true
  }
}

此外,感谢Ivy编译器和语言服务,您只需将strictTemplates设置为true,即可从模板中的TypeScript类型系统中受益。这是默认设置,从Angular 12开始。查看官方文档了解更多详细信息。

确保遵循Angular团队推荐的安全实践并避免使用ElementRef innerHTML,除非您确定自己知道自己在做什么!

使用延迟加载

使用Angular时,您应该构建所谓的SPA,它指的是单页应用程序。这是一种现代类型的应用程序,不同于我们之前创建的传统Web应用程序。

Angular一次性从服务器加载SPA包,并使用JavaScript或客户端路由使用户能够在不同的视图之间导航。

这是当今构建应用程序的现代方法,也是我们使用AngularReactVue.js等现代框架构建应用程序的方式。

Angular提供了一个强大的路由器,具有大量用于客户端路由的功能。因此,一旦掌握了必要的概念,构建SPA就很容易了。但是,这会影响性能,因为我们必须从服务器下载完整的应用程序包。因此,当您的应用程序大小增加时,应用程序的下载时间也会增加!

延迟加载的作用来了,它围绕着当应用程序的用户访问特定模块时推迟加载特定模块的想法。这可以减少应用程序包的实际下载大小,从而使您受益。延迟加载还通过在应用程序首次启动时不加载未使用的模块,而仅在用户触发导航时加载来缩短启动时间。

作为最佳实践,您必须 尽可能在应用程序中延迟加载功能模块。您需要在应用程序启动期间急切加载一个功能模块以显示初始内容。您应该延迟加载所有其他功能模块以提高性能并减少初始包大小。

您可以使用具有动态导入语法Angular路由器的loadChildren属性延迟加载模块。但是感谢Ivy,您还可以延迟加载组件。让我们看一个例子!

首先,确保您有一个设置了Angular路由的项目。使用Angular CLI,您可以通过在生成项目时为ng new命令设置--routing标志或在提示您想要添加Angular路由?时回答“y”来解决这个问题。

打开src/app/app-routing.module.ts文件并延迟加载产品和购物车模块,如下所示:

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

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

import { ProductModule } from './product/product.module';

import { CartModule } from './cart/cart.module';

const routes: Routes = [

    { path: 'product', loadChildren: () => import('./product/product.module').then(m => m.ProductModule) },

    { path: 'cart', loadChildren: () => import('./cart/cart.module').then(m => m.CartModule) }

];

@NgModule({

    imports: [RouterModule.forRoot(routes)],

    exports: [RouterModule]

})

export class AppRoutingModule { }

我们使用路由配置的loadChildren 属性结合import语句来延迟加载模块。

现在,您添加到这些模块的任何组件都将被延迟加载!然而,使用Ivy,我们可以在不需要模块的情况下延迟加载Angular组件。

首先,使用以下命令生成一个组件:

ng generate component header --module=core

核心模块导入这个。

打开src/app/app.component.html文件,更新如下:

<button (click)="lazyLoadHeader()">Load header</button>

<ng-container #header></ng-container>

接下来,打开src/app/app.component.ts文件并更新如下:

import { Component, ComponentFactoryResolver, ViewChild, ViewContainerRef } from '@angular/core';

@Component({

    selector: 'app-root',

    templateUrl: './app.component.html',

    styleUrls: ['./app.component.scss']

})

export class AppComponent {

    title = 'angular-practices-demo';

    @ViewChild('header', { read: ViewContainerRef }) headerContainer: ViewContainerRef | null = null;

    constructor(private  factoryResolver: ComponentFactoryResolver) { }

    async lazyLoadHeader() {

        const { HeaderComponent } = await import('./header/header.component');

        const factory = this.factoryResolver.resolveComponentFactory(HeaderComponent);

    this.headerContainer?.createComponent(factory);

    }

}

当您单击按钮时,您应该看到标题有效!” 这意味着组件按需延迟加载并呈现!

取消订阅RxJS Observables

当你订阅你的组件到RxJS Observables时,你应该总是取消订阅。否则,这会导致不必要的内存泄漏,因为可观察流是打开的,即使在使用它销毁组件之后也是如此。

您可以通过多种方式执行此操作:

  • 销毁组件后在ngOnDestory 事件中取消订阅组件
  • 使用异步管道订阅Observables并在模板中自动取消订阅。

ngFortrackBy一起使用

您可以使用该 ngFor 指令在Angular模板中迭代数组。当您更改数组时,完整的DOM树会重新呈现,这不是性能方面的。为了解决这个问题,你必须使用ngFortrackBy,它唯一标识每个DOM元素并使Angular能够仅重新渲染修改后的元素:

@Component({

    selector: 'my-app',

    template: `

    <li *ngFor="let product of products; trackBy:productById"></li>

    `

})

export class App {

    products:[];

    {id:0, name: "product 1"},

    {id:1, name: "product 2"}

];

productById(index, product){

    return product.id;

}

结论

Angular团队从一开始就采用了最佳实践,通过使用TypeScript进行Angular开发,确保类型安全、更好的错误处理以及与IDE的集成。Angular 12默认启用了严格模式,确保您遵循严格的规则,帮助您构建无错误且可靠的应用程序。在本文中,我们看到了一些可以用来构建可扩展且易于维护的应用程序的最佳实践。

如果你想尝试一些对Angular有深度支持的与框架无关的UI组件——包括数据网格、图表、仪表和输入控件—— 今天就试试 Wijmo

https://www.codeproject.com/Articles/5311989/Angular-Best-Practices-for-2021

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值