Angular Standalone Component

Angular 14以后推出的 standalone component的相关介绍, 包含新式组件的使用方式,与基于ngModule组件之间的相互引用以及如何迁移到新式组件的详细讲解。

什么是Standalone component

standalone 组件是Angular14 版本 新推出的一种 Angular 组件,不需要在 中声明NgModule。这些组件可以直接在另一个组件的模板中使用,而无需成为 NgModule 的一部分,或者导入到 NgModule 中。
首先我们先看一个常规的组件

typescript 复制代码
@Component({
  selector: "test",
  template: `Hello {{ name }}`,
})
class TestComponent {
  name = 'world'
}

这样的组件必须在 NgModule 中声明,否则,它们就不能在另一个组件的模板中使用。

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

}

如何使用standalone组件呢,接下来我们对TestComponent做一下简单的改造。

typescript 复制代码
@Component({
  selector: "test",
  template: `Hello {{ name }}`,
  standalone: true,
})
class TestComponent {
  name = 'world'
}

可以看得到,我们在@component装饰器中添加了一个配置standalone: true,此时我们的组件已经是一个独立组件了。我们只需要将他导入到我们用使用的组件中就可以使用了。

typescript 复制代码
@Component({
  selector: "parent",
  template: `<test></test>`,
  imports: [TestComponent],
})
class ParentComponent {

}

在基于 NgModule 的组件中使用独立组件

有些同学可能会问了,我们的项目是旧项目,基于NgModule的组织结构,如何使用新的独立组件呢?

不要担心, 要在基于 NgModule 的应用程序中利用独立组件,你只需要导入独立组件:

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

在基于模块的应用程序中,使用独立组件非常简单。

但反过来又怎样呢?

在独立组件中使用基于 NgModule 的组件

创建一个 NgModule 并导出基于 NgModule 的组件

typescript 复制代码
@NgModule({
  declarations: [TraditionalComponent],
  // export the NgModule-based component
  exports: [TraditionalComponent], 
})
export class MyModule {

}

然后我们在独立组件中导入 NgModule:

typescript 复制代码
@Component({
  selector: "app-standalone",
  template: `This is a standalone component`,
  standalone: true,
  // Import the NgModule that declares the component
  imports: [MyModule], 
})
class StandaloneComponent {

}

基于 NgModule 的组件可以像任何其他组件一样在独立组件的模板中使用,
所以Ng-Module 组件和独立组件之间的互操作性是无缝的,不必担心会有任何问题。

Standalone pipes

像独立组件一样,我们可以实现独立pipe。在@Pipe装饰器中开启standalone: true配置。

typescript 复制代码
@Pipe({
  name: "capitalise",
  standalone: true,
})
export class CapitalisePipe implements PipeTransform {
  transform(text: string): string {
    return text.toLocaleUpperCase();
  }
}

仅需要将其导入到我们要使用的组件中即可

typescript 复制代码
@Component({
  selector: "app-hello",
  template: `Hello {{ name | capitalise }}`,
  standalone: true,
  imports: [CapitalisePipe],
})
class AppComponent {}

Standalone Directives

实现独立的指令也非常的容易,只需要在指令装饰器的配置项中开启standalone: true

typescript 复制代码
@Directive({
  selector: "[example-directive]",
  standalone: true,
})
class ExampleDirective {}

这样我们就实现的一个独立的指令,可以在用使用的地方导入即可。

使用独立组件进行延迟加载

在没有standalone组件之前,我们通过模块实现懒加载。必须为想要延迟加载的一组组件、管道或指令创建一个模块

typescript 复制代码
const routes: Routes = [
  {
    path: "test",
    loadChildren: () =>
      import("./module-test/moduletest.module").
      then((m) => m.ModuleTestModule),
  },
];

需要创建一个模块并定义它的所有依赖项,并不是因为我们想要封装某些特性并使其可重用,而仅仅是为了延迟加载该内容这一单一目的。

但随着standalone组件的出现,这让懒加载的实现更加容易。

typescript 复制代码
export const routes: Routes = [
  {
    path: "lazy-test",
    loadComponent: () =>
      import("./app-hello")
      .then((m) => m.StandaloneComponent),
  },
];

迁移到Standalone component

可以使用 Angular CLI 自动将应用程序迁移到独立组件

git bash 复制代码
ng generate @angular/core:standalone

可能仍需要做一些小的重构,但 CLI 将为您完成大部分工作.
主要分为以下几步完成:

1.选择“将所有组件、指令和管道转换为独立”选项

2.选择“删除不必要的 NgModule 类”选项。这将尝试删除尽可能多的 NgModule,但可能无法全部删除,因此您需要检查此处的代码并手动删除所有可以删除的模块

3.运行迁移并选择“使用独立 API 引导应用程序”选项