MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

Angular基础

2024-06-017.2k 阅读

一、Angular 简介

Angular 是一款由谷歌开发维护的前端 JavaScript 框架,用于构建高效、复杂且可维护的单页应用程序(SPA)。它诞生于 2010 年,最初名为 AngularJS,在 2016 年发布了 Angular 2.0 版本,对框架进行了全面重写,在设计理念、架构等方面都有了重大改变,并统一命名为 Angular。

Angular 采用了组件化的架构模式,将应用程序分割成一个个可复用的组件,每个组件都有自己独立的逻辑、模板和样式。这种模式不仅使得代码的组织和维护更加容易,还提高了代码的可测试性和复用性。同时,Angular 引入了双向数据绑定机制,使得模型(数据)和视图之间能够自动同步更新,大大简化了前端开发中处理数据与 UI 交互的过程。

二、环境搭建

在开始使用 Angular 进行开发之前,需要先搭建好开发环境。主要步骤如下:

  1. 安装 Node.js:Angular 基于 Node.js 运行,因此需要先安装 Node.js。可以从Node.js 官网下载对应操作系统的安装包进行安装。安装完成后,在命令行中输入 node -vnpm -v 来检查是否安装成功,分别会输出版本号。
  2. 安装 Angular CLI:Angular CLI(命令行界面)是一个强大的工具,用于快速生成、开发和维护 Angular 项目。通过 npm 全局安装 Angular CLI,在命令行中执行以下命令:
npm install -g @angular/cli

安装完成后,输入 ng -v 来检查是否安装成功,会输出版本号等相关信息。 3. 创建新的 Angular 项目:使用 Angular CLI 创建新项目非常简单,在命令行中执行以下命令:

ng new my - app

这里 my - app 是项目名称,可以根据实际需求进行更改。命令执行过程中会提示一些配置选项,如是否使用路由、选择 CSS 预处理器等,可以根据项目需求进行选择。创建完成后,进入项目目录:

cd my - app
  1. 运行项目:在项目目录下执行以下命令启动开发服务器:
ng serve --open

--open 选项会自动打开浏览器并访问 http://localhost:4200,可以看到默认的 Angular 应用页面。每次修改代码保存后,浏览器会自动刷新显示最新内容。

三、组件

  1. 组件基础 组件是 Angular 应用的核心构建块。每个组件都由一个 TypeScript 类、一个 HTML 模板和一个 CSS 样式文件组成(也可以将样式内联到组件类中)。以一个简单的问候组件为例,首先使用 Angular CLI 生成组件:
ng generate component greeting

这会在 src/app 目录下生成一个名为 greeting 的组件文件夹,包含以下文件:

  • greeting.component.ts:组件的 TypeScript 类定义,包含组件的逻辑。
  • greeting.component.html:组件的 HTML 模板,定义了组件的视图结构。
  • greeting.component.css:组件的 CSS 样式文件,用于定义组件的样式。
  • greeting.component.spec.ts:用于编写组件单元测试的文件。

打开 greeting.component.ts 文件,内容大致如下:

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

@Component({
  selector: 'app - greeting',
  templateUrl: './greeting.component.html',
  styleUrls: ['./greeting.component.css']
})
export class GreetingComponent {
  message = 'Hello, Angular!';
}

@Component 装饰器中,selector 定义了组件在 HTML 中使用的标签名,templateUrl 指定了模板文件路径,styleUrls 指定了样式文件路径。在类中定义了一个 message 属性,用于存储问候消息。

greeting.component.html 文件中,可以这样使用这个属性:

<p>{{message}}</p>

这样就会在页面上显示 Hello, Angular!

  1. 组件间通信 在实际应用中,组件之间常常需要进行通信。常见的通信方式有以下几种:
  • 父组件向子组件传值:通过输入属性(@Input())来实现。假设父组件 parent.component.ts 中有一个子组件 child.component.ts,在父组件模板 parent.component.html 中使用子组件并传递数据:
<app - child [childData]="parentData"></app - child>

parent.component.ts 中定义 parentData

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

@Component({
  selector: 'app - parent',
  templateUrl: './parent.component.html',
  styleUrls: ['./parent.component.css']
})
export class ParentComponent {
  parentData = 'Data from parent';
}

child.component.ts 中通过 @Input() 接收数据:

import { Component, Input } from '@angular/core';

@Component({
  selector: 'app - child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css']
})
export class ChildComponent {
  @Input() childData: string;
}

child.component.html 中可以使用 childData

<p>{{childData}}</p>
  • 子组件向父组件传值:通过输出属性(@Output())和事件绑定来实现。在子组件 child.component.ts 中定义一个事件发射器:
import { Component, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'app - child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css']
})
export class ChildComponent {
  @Output() childEvent = new EventEmitter<string>();
  sendData() {
    this.childEvent.emit('Data from child');
  }
}

child.component.html 中添加一个按钮触发事件:

<button (click)="sendData()">Send Data</button>

在父组件 parent.component.html 中监听子组件事件:

<app - child (childEvent)="handleChildEvent($event)"></app - child>

parent.component.ts 中定义处理函数:

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

@Component({
  selector: 'app - parent',
  templateUrl: './parent.component.html',
  styleUrls: ['./parent.component.css']
})
export class ParentComponent {
  handleChildEvent(data: string) {
    console.log('Received data from child:', data);
  }
}
  • 兄弟组件通信:通常可以通过一个共同的父组件作为中间媒介来实现。也可以使用服务(后面会介绍)来进行更灵活的通信。

四、模板语法

  1. 插值表达式 插值表达式是在模板中显示数据最常用的方式,格式为 {{expression}}。例如:
<p>{{message}}</p>

这里 message 是组件类中的属性。插值表达式还可以包含简单的 JavaScript 表达式,如:

<p>{{1 + 2}}</p>

会显示 3。但不建议在插值表达式中包含复杂的逻辑,因为可能会影响性能。

  1. 属性绑定 属性绑定用于动态设置 HTML 元素的属性值。语法为 [attribute]="expression"。例如,要动态设置 img 元素的 src 属性:
<img [src]="imageUrl" alt="My Image">

在组件类中定义 imageUrl 属性:

export class MyComponent {
  imageUrl = 'https://example.com/image.jpg';
}
  1. 事件绑定 事件绑定用于捕获和处理 DOM 事件。语法为 (event)="handlerFunction($event)"。例如,为按钮添加点击事件:
<button (click)="onButtonClick()">Click Me</button>

在组件类中定义 onButtonClick 方法:

export class MyComponent {
  onButtonClick() {
    console.log('Button clicked');
  }
}

$event 是事件对象,可以获取事件的相关信息,如鼠标点击位置等。

  1. 双向数据绑定 双向数据绑定是 Angular 的一个强大特性,它允许在模型和视图之间自动同步更新。通过 ngModel 指令来实现,需要先在模块中导入 FormsModule。例如,一个简单的文本输入框与组件属性双向绑定:
<input [(ngModel)]="userName" type="text">
<p>You entered: {{userName}}</p>

在组件类中定义 userName 属性:

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

@Component({
  selector: 'app - my - component',
  templateUrl: './my - component.html',
  styleUrls: ['./my - component.css']
})
export class MyComponent {
  userName = '';
}

当在输入框中输入内容时,userName 属性会自动更新,同时 <p> 标签中的内容也会实时显示最新的输入值。

五、模块

  1. 模块基础 Angular 应用是模块化的,模块是一个容器,用于组合相关的组件、指令、管道和服务。通过模块,可以更好地组织和管理应用的代码结构。每个 Angular 应用至少有一个根模块,通常命名为 AppModule。使用 Angular CLI 生成项目时,会自动生成 app.module.ts 文件,内容大致如下:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform - browser';
import { AppComponent } from './app.component';

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

@NgModule 装饰器用于定义模块,其中:

  • declarations 数组用于声明该模块中包含的组件、指令和管道。
  • imports 数组用于导入其他模块,这些模块提供的功能可以在本模块中使用。例如 BrowserModule 提供了在浏览器环境中运行所需的基础功能。
  • providers 数组用于注册服务,这些服务可以在整个应用中使用。
  • bootstrap 数组指定应用的根组件,这里是 AppComponent,表示应用从这个组件开始启动。
  1. 特性模块 随着应用规模的扩大,将所有代码都放在根模块中会导致代码变得臃肿和难以维护。这时可以创建特性模块,将相关功能的组件、指令、管道和服务组织在一起。例如,创建一个用户管理特性模块:
ng generate module user - management

这会生成 user - management.module.ts 文件,在其中可以声明用户管理相关的组件等:

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { UserListComponent } from './user - list/user - list.component';
import { UserDetailComponent } from './user - detail/user - detail.component';

@NgModule({
  declarations: [
    UserListComponent,
    UserDetailComponent
  ],
  imports: [
    CommonModule
  ],
  providers: [],
  exports: [
    UserListComponent,
    UserDetailComponent
  ]
})
export class UserManagementModule { }

CommonModule 提供了一些常用的指令,如 ngIfngFor 等。exports 数组用于指定哪些组件、指令或管道可以被其他模块使用。

然后在 AppModule 中导入 UserManagementModule

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform - browser';
import { AppComponent } from './app.component';
import { UserManagementModule } from './user - management/user - management.module';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    UserManagementModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

这样就可以在 AppComponent 或其他相关组件的模板中使用 UserManagementModule 中导出的组件了。

六、指令

  1. 内置指令
  • 结构指令:用于改变 DOM 的结构。常见的结构指令有 ngIfngForngSwitch
    • ngIf:根据表达式的值来决定是否渲染一个元素或一组元素。例如:
<div *ngIf="isLoggedIn">
  <p>Welcome, user!</p>
</div>

在组件类中定义 isLoggedIn 属性:

export class MyComponent {
  isLoggedIn = true;
}

isLoggedIntrue 时,<div> 及其内部内容会被渲染到 DOM 中;为 false 时则不会渲染。 - ngFor:用于在模板中迭代一个数组或对象,并为每个元素创建一个模板实例。例如,遍历一个用户列表:

<ul>
  <li *ngFor="let user of users">{{user.name}}</li>
</ul>

在组件类中定义 users 数组:

export class MyComponent {
  users = [
    { name: 'Alice' },
    { name: 'Bob' },
    { name: 'Charlie' }
  ];
}

这会在页面上显示一个无序列表,每个列表项是用户的名字。 - ngSwitch:根据表达式的值在多个模板之间进行切换。例如:

<div [ngSwitch]="user.role">
  <p *ngSwitchCase="'admin'">This user is an admin.</p>
  <p *ngSwitchCase="'user'">This user is a regular user.</p>
  <p *ngSwitchDefault">Unknown role.</p>
</div>

在组件类中定义 user 对象:

export class MyComponent {
  user = { role: 'admin' };
}
  • 属性指令:用于改变元素的外观或行为。常见的属性指令有 ngStylengClass
    • ngStyle:用于动态设置元素的样式。例如:
<div [ngStyle]="{ 'background - color': isHighlighted? 'yellow' : 'white' }">
  <p>Some text</p>
</div>

在组件类中定义 isHighlighted 属性:

export class MyComponent {
  isHighlighted = true;
}

isHighlightedtrue 时,<div> 的背景颜色为黄色;为 false 时为白色。 - ngClass:用于动态添加或移除 CSS 类。例如:

<div [ngClass]="{ 'active': isActive }">
  <p>Some text</p>
</div>

在 CSS 文件中定义 .active 类:

.active {
  border: 1px solid blue;
}

在组件类中定义 isActive 属性:

export class MyComponent {
  isActive = true;
}

isActivetrue 时,<div> 会添加 .active 类,显示蓝色边框;为 false 时则移除该类。

  1. 自定义指令 除了使用内置指令,还可以创建自定义指令来满足特定的业务需求。以一个简单的高亮指令为例,使用 Angular CLI 生成指令:
ng generate directive highlight

这会生成 highlight.directive.ts 文件,内容如下:

import { Directive, ElementRef, HostListener } from '@angular/core';

@Directive({
  selector: '[appHighlight]'
})
export class HighlightDirective {
  constructor(private el: ElementRef) { }

  @HostListener('mouseenter') onMouseEnter() {
    this.highlight('yellow');
  }

  @HostListener('mouseleave') onMouseLeave() {
    this.highlight(null);
  }

  private highlight(color: string) {
    this.el.nativeElement.style.backgroundColor = color;
  }
}

@Directive 装饰器中,selector 定义了指令在 HTML 中使用的属性名。通过 ElementRef 可以访问指令所在的 DOM 元素。@HostListener 用于监听 DOM 事件,这里监听了 mouseentermouseleave 事件,分别在鼠标进入和离开元素时调用 highlight 方法来设置或移除背景颜色。

在模板中使用该指令:

<p appHighlight>Highlight me on hover</p>

当鼠标悬停在 <p> 元素上时,背景颜色会变为黄色;鼠标离开时恢复原状。

七、管道

  1. 管道基础 管道用于对数据进行转换和格式化。Angular 提供了一些内置管道,如 DatePipeUpperCasePipeLowerCasePipe 等。使用管道的语法为 expression | pipeName:arguments。例如,使用 DatePipe 格式化日期:
<p>{{today | date:'yyyy - MM - dd' }}</p>

在组件类中定义 today 属性:

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

@Component({
  selector: 'app - my - component',
  templateUrl: './my - component.html',
  styleUrls: ['./my - component.css']
})
export class MyComponent {
  today = new Date();
}

这会将当前日期格式化为 yyyy - MM - dd 的形式显示在页面上。

  1. 自定义管道 如果内置管道不能满足需求,可以创建自定义管道。以一个简单的截取字符串管道为例,使用 Angular CLI 生成管道:
ng generate pipe truncate

这会生成 truncate.pipe.ts 文件,内容如下:

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'truncate'
})
export class TruncatePipe implements PipeTransform {
  transform(value: string, limit: number): string {
    if (value.length <= limit) {
      return value;
    }
    return value.substring(0, limit) + '...';
  }
}

@Pipe 装饰器中,name 定义了管道在模板中使用的名称。PipeTransform 接口要求实现 transform 方法,这里根据传入的 limit 参数截取字符串并添加省略号。

在模板中使用该管道:

<p>{{longText | truncate:10 }}</p>

在组件类中定义 longText 属性:

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

@Component({
  selector: 'app - my - component',
  templateUrl: './my - component.html',
  styleUrls: ['./my - component.css']
})
export class MyComponent {
  longText = 'This is a very long text that needs to be truncated.';
}

这样会显示 This is a...

八、服务

  1. 服务基础 服务是一个可注入的类,用于在应用中共享数据和功能。它通常用于处理与业务逻辑相关的操作,如数据获取、存储管理等。使用 Angular CLI 生成服务:
ng generate service user

这会生成 user.service.ts 文件,内容大致如下:

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

@Injectable({
  providedIn: 'root'
})
export class UserService {
  private users = [
    { name: 'Alice', age: 25 },
    { name: 'Bob', age: 30 }
  ];

  getUsers() {
    return this.users;
  }
}

@Injectable 装饰器用于标记该类为可注入的服务,providedIn: 'root' 表示该服务在应用的根模块中提供,整个应用都可以使用。这里定义了一个简单的 UserService,包含一个私有数组 users 和一个 getUsers 方法用于获取用户列表。

  1. 注入服务 要在组件中使用服务,需要将服务注入到组件中。例如,在 app.component.ts 中使用 UserService
import { Component } from '@angular/core';
import { UserService } from './user.service';

@Component({
  selector: 'app - root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  users;
  constructor(private userService: UserService) {
    this.users = this.userService.getUsers();
  }
}

在组件的构造函数中注入 UserService,然后就可以调用服务的方法获取用户列表并赋值给组件的 users 属性。在 app.component.html 中可以显示用户列表:

<ul>
  <li *ngFor="let user of users">{{user.name}} - {{user.age}}</li>
</ul>

这样就可以在页面上显示用户的名字和年龄。

  1. 服务间依赖注入 服务之间也可以相互依赖。例如,有一个 AuthService 用于验证用户身份,UserService 可能依赖于 AuthService 来判断用户是否有权限获取用户列表。假设 auth.service.ts 如下:
import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class AuthService {
  isAuthenticated() {
    // 这里可以实现实际的身份验证逻辑,例如检查 token 等
    return true;
  }
}

user.service.ts 中注入 AuthService

import { Injectable } from '@angular/core';
import { AuthService } from './auth.service';

@Injectable({
  providedIn: 'root'
})
export class UserService {
  private users = [
    { name: 'Alice', age: 25 },
    { name: 'Bob', age: 30 }
  ];
  constructor(private authService: AuthService) { }

  getUsers() {
    if (this.authService.isAuthenticated()) {
      return this.users;
    }
    return [];
  }
}

这样只有在用户通过身份验证时,UserService 才能返回用户列表。

九、路由

  1. 路由基础 路由用于在单页应用中实现页面导航和视图切换。Angular 提供了强大的路由功能。在创建项目时,可以通过 Angular CLI 选择是否启用路由。如果选择启用,会在 app.module.ts 中导入 RouterModule 并配置基本路由。例如,有两个组件 HomeComponentAboutComponent,配置路由如下:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform - browser';
import { AppComponent } from './app.component';
import { HomeComponent } from './home/home.component';
import { AboutComponent } from './about/about.component';
import { RouterModule, Routes } from '@angular/router';

const routes: Routes = [
  { path: '', component: HomeComponent },
  { path: 'about', component: AboutComponent }
];

@NgModule({
  declarations: [
    AppComponent,
    HomeComponent,
    AboutComponent
  ],
  imports: [
    BrowserModule,
    RouterModule.forRoot(routes)
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Routes 数组定义了路由配置,每个对象包含 path(路由路径)和 component(对应的组件)。RouterModule.forRoot(routes) 用于将路由配置注册到应用的根模块。

app.component.html 中添加导航链接和路由出口:

<ul>
  <li><a routerLink="/">Home</a></li>
  <li><a routerLink="/about">About</a></li>
</ul>
<router - outlet></router - outlet>

routerLink 指令用于创建路由链接,router - outlet 是路由出口,用于显示匹配路由的组件。

  1. 路由参数 路由可以传递参数。例如,有一个 UserDetailComponent 用于显示特定用户的详细信息,路由配置如下:
const routes: Routes = [
  { path: 'user/:id', component: UserDetailComponent }
];

这里 :id 是参数名。在组件中获取参数,在 user - detail.component.ts 中:

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';

@Component({
  selector: 'app - user - detail',
  templateUrl: './user - detail.component.html',
  styleUrls: ['./user - detail.component.css']
})
export class UserDetailComponent implements OnInit {
  userId: string;
  constructor(private route: ActivatedRoute) { }

  ngOnInit() {
    this.userId = this.route.snapshot.paramMap.get('id');
  }
}

通过 ActivatedRoutesnapshot.paramMap.get('id') 可以获取路由参数 id 的值。在模板中可以根据 userId 显示相应用户的详细信息。

  1. 嵌套路由 在实际应用中,常常需要使用嵌套路由。例如,在 UserComponent 下有 UserListComponentUserDetailComponent,路由配置如下:
const routes: Routes = [
  {
    path: 'users', component: UserComponent, children: [
      { path: '', component: UserListComponent },
      { path: ':id', component: UserDetailComponent }
    ]
  }
];

UserComponent 的模板 user.component.html 中添加子路由出口:

<router - outlet></router - outlet>

这样当访问 /users 时,会显示 UserListComponent;访问 /users/1 时,会显示 UserDetailComponent 并传递参数 1

十、HTTP 客户端

  1. HTTP 基础 在前端应用中,经常需要与后端服务器进行数据交互,Angular 提供了 HttpClient 模块来处理 HTTP 请求。首先在模块中导入 HttpClientModule,例如在 app.module.ts 中:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform - browser';
import { AppComponent } from './app.component';
import { HttpClientModule } from '@angular/common/http';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

然后在服务或组件中注入 HttpClient 来发送 HTTP 请求。以一个简单的用户服务获取用户列表为例,在 user.service.ts 中:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class UserService {
  private apiUrl = 'https://example.com/api/users';

  constructor(private http: HttpClient) { }

  getUsers(): Observable<any> {
    return this.http.get(this.apiUrl);
  }
}

这里 http.get 方法发送一个 GET 请求到指定的 API 地址,并返回一个 Observable 对象。Observable 是 RxJS(Reactive Extensions for JavaScript)库中的核心概念,用于处理异步操作。

在组件中使用该服务获取用户列表,在 app.component.ts 中:

import { Component, OnInit } from '@angular/core';
import { UserService } from './user.service';

@Component({
  selector: 'app - root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  users;
  constructor(private userService: UserService) { }

  ngOnInit() {
    this.userService.getUsers().subscribe(data => {
      this.users = data;
    });
  }
}

通过 subscribe 方法订阅 Observable,当 HTTP 请求成功返回数据时,将数据赋值给 users 属性。

  1. 发送其他类型请求 除了 GET 请求,HttpClient 还支持 POST、PUT、DELETE 等请求方法。例如,发送一个 POST 请求创建新用户:
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class UserService {
  private apiUrl = 'https://example.com/api/users';

  constructor(private http: HttpClient) { }

  createUser(user: any): Observable<any> {
    return this.http.post(this.apiUrl, user);
  }
}

这里 http.post 方法的第一个参数是 API 地址,第二个参数是要发送的数据。在组件中使用:

import { Component, OnInit } from '@angular/core';
import { UserService } from './user.service';

@Component({
  selector: 'app - root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  newUser = { name: 'New User', age: 20 };
  constructor(private userService: UserService) { }

  ngOnInit() {
    this.userService.createUser(this.newUser).subscribe(response => {
      console.log('User created:', response);
    });
  }
}

同样通过 subscribe 方法处理请求的响应。

  1. 处理 HTTP 错误 在发送 HTTP 请求时,可能会遇到各种错误,如网络问题、服务器错误等。可以通过 catchError 操作符来处理错误。首先导入 catchError 操作符和 throwError 函数:
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { throwError } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class UserService {
  private apiUrl = 'https://example.com/api/users';

  constructor(private http: HttpClient) { }

  getUsers(): Observable<any> {
    return this.http.get(this.apiUrl).pipe(
      catchError(error => {
        console.error('Error fetching users:', error);
        return throwError('An error occurred while fetching users.');
      })
    );
  }
}

在组件中订阅时,可以捕获错误:

import { Component, OnInit } from '@angular/core';
import { UserService } from './user.service';

@Component({
  selector: 'app - root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  users;
  constructor(private userService: UserService) { }

  ngOnInit() {
    this.userService.getUsers().subscribe(data => {
      this.users = data;
    }, error => {
      console.error('Component caught error:', error);
    });
  }
}

这样在请求出错时,会在控制台打印错误信息,并将错误传递给 subscribe 的第二个回调函数进行处理。

通过以上对 Angular 基础的详细介绍,包括组件、模板语法、模块、指令、管道、服务、路由和 HTTP 客户端等方面,希望能帮助开发者快速入门并深入理解 Angular 的核心概念和开发方法,从而能够构建出高质量的前端应用程序。在实际开发中,还需要不断实践和探索,结合具体业务需求充分发挥 Angular 的强大功能。