Skip to Content
Nextra 4.0 is released 🎉
框架 & 库Angular

Angular 学习指南

Angular 是一个由 Google 开发的开源前端框架,用于构建单页应用程序。它采用 TypeScript 作为主要语言,提供了完整的开发工具链和丰富的生态系统。

🚀 快速开始

创建 Angular 项目

# 安装 Angular CLI npm install -g @angular/cli # 创建新项目 ng new my-angular-app # 启动开发服务器 ng serve # 构建生产版本 ng build --prod

📚 核心概念

TypeScript 基础

Angular 使用 TypeScript 作为主要语言,提供类型安全和更好的开发体验:

// 接口定义 interface User { id: number; name: string; email: string; } // 类型注解 let user: User = { id: 1, name: 'John Doe', email: 'john@example.com' };

组件基础

Angular 组件是构建应用的基本单元:

import { Component } from '@angular/core'; @Component({ selector: 'app-welcome', template: ` <h1>Hello, {{ name }}!</h1> <p>Welcome to Angular</p> `, styleUrls: ['./welcome.component.css'] }) export class WelcomeComponent { name = 'Angular'; }

模板语法

Angular 使用强大的模板语法:

<!-- 插值 --> <h1>{{ title }}</h1> <!-- 属性绑定 --> <img [src]="imageUrl" [alt]="imageAlt"> <!-- 事件绑定 --> <button (click)="onClick()">Click me</button> <!-- 双向绑定 --> <input [(ngModel)]="name" placeholder="Enter name"> <!-- 结构指令 --> <div *ngIf="isVisible">This is visible</div> <ul> <li *ngFor="let item of items">{{ item.name }}</li> </ul>

⚡ 生命周期钩子

Angular 提供了丰富的生命周期钩子:

import { Component, OnInit, OnDestroy, OnChanges, AfterViewInit } from '@angular/core'; @Component({ selector: 'app-lifecycle', template: '<div>Lifecycle Demo</div>' }) export class LifecycleComponent implements OnInit, OnDestroy, OnChanges, AfterViewInit { ngOnInit() { // 组件初始化时调用 console.log('Component initialized'); } ngOnChanges(changes: SimpleChanges) { // 输入属性变化时调用 console.log('Input properties changed:', changes); } ngAfterViewInit() { // 视图初始化后调用 console.log('View initialized'); } ngOnDestroy() { // 组件销毁时调用 console.log('Component destroyed'); } }

🎯 常用生命周期钩子

钩子用途调用时机
ngOnInit组件初始化组件初始化后,输入属性设置后
ngOnChanges监听输入变化输入属性变化时
ngDoCheck自定义变更检测每次变更检测周期
ngAfterContentInit内容投影后外部内容投影到组件后
ngAfterContentChecked内容检查后每次内容检查后
ngAfterViewInit视图初始化后组件视图初始化后
ngAfterViewChecked视图检查后每次视图检查后
ngOnDestroy组件销毁组件销毁前

🔧 数据绑定

属性绑定

@Component({ selector: 'app-property-binding', template: ` <img [src]="imageUrl" [alt]="imageAlt"> <button [disabled]="isDisabled">Submit</button> <div [class.active]="isActive">Active content</div> ` }) export class PropertyBindingComponent { imageUrl = 'assets/logo.png'; imageAlt = 'Logo'; isDisabled = false; isActive = true; }

事件绑定

@Component({ selector: 'app-event-binding', template: ` <button (click)="onClick()">Click me</button> <input (input)="onInput($event)" placeholder="Type something"> <form (submit)="onSubmit($event)"> <button type="submit">Submit</button> </form> ` }) export class EventBindingComponent { onClick() { console.log('Button clicked'); } onInput(event: Event) { const target = event.target as HTMLInputElement; console.log('Input value:', target.value); } onSubmit(event: Event) { event.preventDefault(); console.log('Form submitted'); } }

双向绑定

import { FormsModule } from '@angular/forms'; @Component({ selector: 'app-two-way-binding', template: ` <input [(ngModel)]="name" placeholder="Enter name"> <p>Hello, {{ name }}!</p> <select [(ngModel)]="selectedOption"> <option value="">Select an option</option> <option value="option1">Option 1</option> <option value="option2">Option 2</option> </select> <p>Selected: {{ selectedOption }}</p> ` }) export class TwoWayBindingComponent { name = ''; selectedOption = ''; }

📦 服务和依赖注入

创建服务

import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class UserService { private apiUrl = 'https://api.example.com/users'; constructor(private http: HttpClient) {} getUsers(): Observable<User[]> { return this.http.get<User[]>(this.apiUrl); } getUser(id: number): Observable<User> { return this.http.get<User>(`${this.apiUrl}/${id}`); } createUser(user: User): Observable<User> { return this.http.post<User>(this.apiUrl, user); } }

使用服务

@Component({ selector: 'app-user-list', template: ` <div *ngFor="let user of users"> <h3>{{ user.name }}</h3> <p>{{ user.email }}</p> </div> ` }) export class UserListComponent implements OnInit { users: User[] = []; constructor(private userService: UserService) {} ngOnInit() { this.userService.getUsers().subscribe( users => this.users = users, error => console.error('Error fetching users:', error) ); } }

🛠️ 路由管理

配置路由

import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { HomeComponent } from './home/home.component'; import { AboutComponent } from './about/about.component'; import { UserDetailComponent } from './user-detail/user-detail.component'; const routes: Routes = [ { path: '', component: HomeComponent }, { path: 'about', component: AboutComponent }, { path: 'users/:id', component: UserDetailComponent }, { path: '**', redirectTo: '' } ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { }

使用路由

@Component({ selector: 'app-navigation', template: ` <nav> <a routerLink="/" routerLinkActive="active" [routerLinkActiveOptions]="{exact: true}">Home</a> <a routerLink="/about" routerLinkActive="active">About</a> <a [routerLink]="['/users', userId]" routerLinkActive="active">User Profile</a> </nav> <router-outlet></router-outlet> ` }) export class NavigationComponent { userId = 1; }

🔍 表单处理

模板驱动表单

import { FormsModule } from '@angular/forms'; @Component({ selector: 'app-template-form', template: ` <form #userForm="ngForm" (ngSubmit)="onSubmit(userForm)"> <div> <label for="name">Name:</label> <input id="name" name="name" [(ngModel)]="user.name" required> </div> <div> <label for="email">Email:</label> <input id="email" name="email" [(ngModel)]="user.email" type="email" required email> </div> <button type="submit" [disabled]="!userForm.valid">Submit</button> </form> ` }) export class TemplateFormComponent { user = { name: '', email: '' }; onSubmit(form: NgForm) { if (form.valid) { console.log('Form submitted:', this.user); } } }

响应式表单

import { FormBuilder, FormGroup, Validators } from '@angular/forms'; @Component({ selector: 'app-reactive-form', template: ` <form [formGroup]="userForm" (ngSubmit)="onSubmit()"> <div> <label for="name">Name:</label> <input id="name" formControlName="name"> <div *ngIf="userForm.get('name')?.invalid && userForm.get('name')?.touched"> Name is required </div> </div> <div> <label for="email">Email:</label> <input id="email" formControlName="email" type="email"> <div *ngIf="userForm.get('email')?.invalid && userForm.get('email')?.touched"> Please enter a valid email </div> </div> <button type="submit" [disabled]="userForm.invalid">Submit</button> </form> ` }) export class ReactiveFormComponent implements OnInit { userForm: FormGroup; constructor(private fb: FormBuilder) {} ngOnInit() { this.userForm = this.fb.group({ name: ['', Validators.required], email: ['', [Validators.required, Validators.email]] }); } onSubmit() { if (this.userForm.valid) { console.log('Form submitted:', this.userForm.value); } } }

⚡ 性能优化

OnPush 变更检测策略

import { ChangeDetectionStrategy } from '@angular/core'; @Component({ selector: 'app-optimized', template: '<div>{{ data }}</div>', changeDetection: ChangeDetectionStrategy.OnPush }) export class OptimizedComponent { @Input() data: any; }

TrackBy 函数

@Component({ selector: 'app-user-list', template: ` <div *ngFor="let user of users; trackBy: trackByUserId"> {{ user.name }} </div> ` }) export class UserListComponent { users: User[] = []; trackByUserId(index: number, user: User): number { return user.id; } }

异步管道

@Component({ selector: 'app-async-data', template: ` <div *ngIf="users$ | async as users"> <div *ngFor="let user of users"> {{ user.name }} </div> </div> ` }) export class AsyncDataComponent { users$ = this.userService.getUsers(); constructor(private userService: UserService) {} }

📖 学习资源

官方文档

实用工具和库

  • Angular Material: Google 的 Material Design 组件库
  • PrimeNG: 丰富的 UI 组件库
  • NgRx: 状态管理库
  • Angular Universal: 服务端渲染
  • Angular PWA: 渐进式 Web 应用

🔍 调试工具

  • Angular DevTools: 浏览器扩展,用于调试 Angular 应用
  • Augury: Angular 应用调试工具
  • Angular CLI: 命令行工具,提供开发、构建、测试等功能

最后更新: 2024年

最近更新:12/9/2025, 2:17:54 AM