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