Angular 是一个现代 Web 前端开发框架,主要特点是 MVVM 双向绑定数据、纯粹 TypeScript 编写、基于 IOC 进行控制反转。是前端工程化的佼佼者,本文记录在 Angular 中必须知道的 20 个概念。
Angular CLI
Angular CLI 是一个命令行工具,用来创建、开发和维护 Angular 项目。
Angular CLI 的主要功能包括:
- 创建项目:通过
ng new可以直接创建一个新项目或者工作区间 - 生成代码:通过
ng generate可以快速创建组件,服务和其他类型的代码 - 运行项目:通过
ng serve可以启动一个本地服务并且运行当前的 Angular 项目 - 构建项目:通过
ng build可以打包当前 Angular 项目,输出到 dist 目录 - 测试项目:通过
ng test可以运行当前项目中的测试项 - 升级项目:通过
ng update可以直接升级项目中的 Angular 依赖项版本
组件(Component)
组件是 Angular 应用中的最小组成单元,整个应用程序界面就是靠多个组件组合而成。
组件是由 HTML 模板、CSS 样式和 TypeScript 类三部分构成。
服务(Service)
服务是 Angular 中一种专注于实现业务逻辑和状态管理的单例类,它通过依赖注入实现在不同组件之间的复用,将数据处理从组件中剥离出来,让应用结构更加清晰。
下面是一个服务的定义代码
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root' // 这一行表明服务是单例的,并在根目录注入
})
export class DataService {
private data: string[] = [];
constructor() { }
addData(item: string) {
this.data.push(item);
}
getData() {
return this.data;
}
}
模块(Module)
由于Angular在打包的时候有大小限制(虽然可以该配置文件调整),官方推荐做法是通过模块进行切分,模块简单来说就是一堆组件和服务的集合,通过按需加载可以提高应用的性能,在开发的时候使用模块也可以更好地划分边界。
独立组件
独立组件其实就是给组件打上 standalone:true 属性,独立组件不再依赖在 NgModule 中声明的组件,在组件内部直接处理依赖,简化代码结构。
独立组件现在是 Angular 开发的趋势,现在使用 CLI 构建的项目都是使用独立组件。
下面是独立组件的定义代码,只要简单的代码就可以将组件变为独立组件。
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
@Component({
selector: 'app-standalone-example',
standalone: true,
imports: [CommonModule],
template: `
<div *ngIf="true">Hello, I am a standalone component!</div>
`
})
export class StandaloneExampleComponent { }
导入(imports)
import 严格来说不算是 Angular 的独有概念,而是 JavaScript 在工程化探索中发展出来的概念,搭配上 export 来使用,实现代码隔离和代码引用。
Angular 中的 imports 是一个数组,指定了需要用到的在其他他模块中定义的组件、指令和服务等,Angular 模块之间的依赖关系都是依靠 imports 。
单文件组件
单文件组件是指将 HTML 模板,CSS 样式和 TypeScript 代码全部封装在一个文件中,类似于 Vue 开发中的 .vue 文件。
单文件组件适用于比较简单和清晰的小组件,搭配上面的独立组件,简化组件的结构,降低维护成本。
信号
signal 是 Angular 中一个比较新的概念,它提供了一种新的数据绑定变更检测机制,可以替代原来的数据变更检测,提高渲染的性能。
生命周期
Angular 中的生命周期是指组件从创建、渲染、变更检测、最后销毁的全过程,每个过程都预留了钩子方法,供开发者自定义代码,精确管理组件。
在创建时对应的方法是 constructor ,其实这就是标准的类空构造器,Angular 中组件的创建遵循面向对象。
变更检测包括了 ngOnInit 、 ngOnChanges 、 ngDoCheck 、 ngAfterContentInit 、ngAfterViewInit 、 ngAfterViewChecked 六个方法,其中每个方法的执行时间和时机都是不一样的。
渲染包括了 afterNextRender afterEveryRender 两个方法。
销毁只有 ngOnDestroy 一个方法,在组件被回收时触发。
模板
模板是组件中定义结构的 HTML 代码,使用标准的 HTML 语法加上 Angular 特定的表达式和指令实现,组件通过模板将逻辑与视图分离。
延迟视图
延迟视图是 Angular 在 v17引入的一个新功能,它使用声明式语法指定了模板中不需要立即加载的部分。使用 @defer 进行定义。
数据绑定
数据绑定是 Angular 的核心理念,通过 MVVM 的机制实现数据和界面的连接,在HTML模板中,可以直接使用 {{}} 进行绑定,初次之外还提供了 ngModel 来进行双向绑定,方便输入框的数据同步,不过在做数据输入时,更常见的方式是使用响应式表单,下文会介绍。
<div>{{name}}</div>
事件监听
事件监听也是 Angular 的核心部分,通过事件发生器进行包装,将 DOM 的原生事件和自定义的事件发送到 ViewModel 中。
<button (click)="onClick($event)">按钮</button>
响应式表单
响应式表单是 Angular 中一个非常有用的组成部分,它将数据的输入使用表单进行收集,在用户输入的时候,表单中的内容也跟着变化,当提交表单时,可以直接从表单中构建一个对象使用。
响应式表单和 ngModel 的区别主要在于控制位置,响应式表单可以显示的控制整个数据流,而 ngModel 是基于双向绑定进行隐式控制,在面对复杂的输入时捉襟见肘。
依赖注入
依赖注入在整个软件开发领域不是什么新东西,但是在前端工程化开发中属于新技术,依赖注入和原生开发的最大区别就是依赖对象的创建来源是否可管理。
在 Angular 中默认使用依赖注入,所有需要的依赖都可以通过构造器进行注入。
public class LoginComponent{
public construction(private authService : AuthService){
}
onLogin(){
this.authService.login();
}
}
输入(Input)
Input 在 Angular 中的作用是子组件用于接收父组件传递的数据,在子组件中给对应的变量加上 Input 标签,在父组件的模板中可以直接使用数据绑定将数据传递给子组件的变量中。
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
@Component({
selector: 'app-example',
template: `
<div *ngIf="true">Hello, I am a standalone component!</div>
`
})
export class ExampleComponent {
@Input()
name:string;
}
// 用法
<app-example [name]="1"></app-example>
输出(Output)
Output 在 Angular 中的作用是子组件向父组件传递数据,在子组件中给对应的变量加上 Output 标签,在父组件的模板中可以直接使用事件绑定接受父组件传递的数据。
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
@Component({
selector: 'app-example',
template: `
<div *ngIf="true">Hello, I am a standalone component!</div>
`
})
export class ExampleComponent {
@Onput()
changed: = new EventEmitter<string>();
}
// 用法
<app-example (changed)="onChildChange($event)"></app-example>
管道(Pipe)
Pipe 是 Angular 中一个重要的机制,用于在模板中转换数据,通过特定的管道符 | 来连接输入和输出,将数据的处理隔离,保持组件的干净。
<div>{{ birthday | date:'fullDate' }}</div>
事件发生器(EventEmitter)
EventEmitter 是 Angular 中一个用于在组件之间传递事件的类,它一般要配合上面的 Output 来使用,用于将子组件中事件发送到父组件中。