跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Python

【Angular主要内容归纳】

@Angular主要内容归纳 Angular 完整教程 - 核心内容详解 目录 组件 (Components) 模块 (Modules) 服务 (Services) 依赖注入 (Dependency Injection) 路由 (Routing) 数据绑定 (Data Binding) 指令 (Directives) 管道 (Pipes) HTTP 客户端 表单 (Forms) 生命周期钩子 (L…

黑客帝国发布于 2026/4/6更新于 2026/9/136K 浏览

@Angular主要内容归纳

Angular 完整教程 - 核心内容详解

目录

  1. 组件 (Components)
  2. 模块 (Modules)
  3. 服务 (Services)
  4. 依赖注入 (Dependency Injection)
  5. 路由 (Routing)
  6. 数据绑定 (Data Binding)
  7. 指令 (Directives)
  8. 管道 (Pipes)
  9. HTTP 客户端
  10. 表单 (Forms)
  11. 生命周期钩子 (Lifecycle Hooks)
  12. RxJS 和 Observable
  13. 状态管理
  14. 测试

1. 组件 (Components)

组件是 Angular 应用的基本构建块,每个组件包含:

  • 模板 (Template): HTML 视图
  • 类 (Class): 组件逻辑和属性
  • 样式 (Styles): CSS/SCSS 样式
  • 元数据 (Metadata): @Component 装饰器
示例:基础组件
// app.component.tsimport{ Component }from'@angular/core';@Component({ selector:'app-root', templateUrl:'./app.component.html', styleUrls:['./app.component.css']})exportclassAppComponent{ title ='我的 Angular 应用'; count =0;increment(){this.count++;}decrement(){this.count--;}}
<!-- app.component.html --><divclass="container"><h1>{{ title }}</h1><p>计数器: {{ count }}</p><button(click)="increment()">增加</button><button(click)="decrement()">减少</button></div>
示例:带输入输出的组件
// user-card.component.tsimport{ Component, Input, Output, EventEmitter }from'@angular/core';@Component({ selector:'app-user-card', template:` <div> <h3>{{ user.name }}</h3> <p>邮箱: {{ user.email }}</p> <button (click)="onSelect()">选择用户</button> </div> `})exportclassUserCardComponent{@Input() user!:{ name:string; email:string};@Output() userSelected =newEventEmitter<string>();onSelect(){this.userSelected.emit(this.user.email);}}
// parent.component.ts@Component({ selector:'app-parent', template:` <app-user-card [user]="currentUser" (userSelected)="handleUserSelection($event)"> </app-user-card> `})exportclassParentComponent{ currentUser ={ name:'张三', email:'[email protected]'};handleUserSelection(email:string){console.log('选中的用户邮箱:', email);}}

2. 模块 (Modules)

模块用于组织应用代码,NgModule 是 Angular 的模块系统。

示例:根模块
// app.module.tsimport{ NgModule }from'@angular/core';import{ BrowserModule }from'@angular/platform-browser';import{ FormsModule }from'@angular/forms';import{ HttpClientModule }from'@angular/common/http';import{ AppComponent }from'./app.component';import{ UserCardComponent }from'./user-card.component';import{ UserService }from'./user.service';@NgModule({ declarations:[ AppComponent, UserCardComponent ], imports:[ BrowserModule, FormsModule, HttpClientModule ], providers:[ UserService ], bootstrap:[AppComponent]})exportclassAppModule{}
示例:功能模块
// user.module.tsimport{ NgModule }from'@angular/core';import{ CommonModule }from'@angular/common';import{ UserListComponent }from'./user-list.component';import{ UserDetailComponent }from'./user-detail.component';import{ UserService }from'./user.service';@NgModule({ declarations:[ UserListComponent, UserDetailComponent ], imports:[ CommonModule ], providers:[ UserService ], exports:[ UserListComponent ]})exportclassUserModule{}

3. 服务 (Services)

服务用于封装业务逻辑、数据访问和共享功能。

示例:基础服务
// user.service.tsimport{ Injectable }from'@angular/core';import{ HttpClient }from'@angular/common/http';import{ Observable }from'rxjs';exportinterfaceUser{ id:number; name:string; email:string;}@Injectable({ providedIn:'root'// 根级别注入,单例模式})exportclassUserService{private apiUrl ='https://api.example.com/users';constructor(private http: HttpClient){}getUsers(): Observable<User[]>{returnthis.http.get<User[]>(this.apiUrl);}getUserById(id:number): Observable<User>{returnthis.http.get<User>(`${this.apiUrl}/${id}`);}createUser(user: User): Observable<User>{returnthis.http.post<User>(this.apiUrl, user);}updateUser(id:number, user: Partial<User>): Observable<User>{returnthis.http.put<User>(`${this.apiUrl}/${id}`, user);}deleteUser(id:number): Observable<void>{returnthis.http.delete<void>(`${this.apiUrl}/${id}`);}}
示例:带缓存的服务
// product.service.tsimport{ Injectable }from'@angular/core';import{ BehaviorSubject, Observable }from'rxjs';import{ tap }from'rxjs/operators';@Injectable({ providedIn:'root'})exportclassProductService{private productsSubject =newBehaviorSubject<any[]>([]);public products$ =this.productsSubject.asObservable();constructor(private http: HttpClient){this.loadProducts();}privateloadProducts(){this.http.get<any[]>('/api/products').pipe(tap(products =>this.productsSubject.next(products))).subscribe();}getProducts(): Observable<any[]>{returnthis.products$;}addProduct(product:any){const current =this.productsSubject.value;this.productsSubject.next([...current, product]);}}

4. 依赖注入 (Dependency Injection)

Angular 的依赖注入系统自动管理依赖关系。

示例:构造函数注入
// component.tsimport{ Component }from'@angular/core';import{ UserService }from'./user.service';@Component({ selector:'app-user-list', template:'<div>用户列表</div>'})exportclassUserListComponent{constructor(private userService: UserService){// Angular 自动注入 UserService}ngOnInit(){this.userService.getUsers().subscribe(users =>{console.log(users);});}}
示例:可选依赖和注入令牌
// logger.service.tsimport{ Injectable, InjectionToken, Optional, Inject }from'@angular/core';exportconstLOG_LEVEL=newInjectionToken<string>('LOG_LEVEL');@Injectable({ providedIn:'root'})exportclassLoggerService{constructor(@Optional()@Inject(LOG_LEVEL)private logLevel:string='INFO'){console.log('日志级别:',this.logLevel);}log(message:string){console.log(`[${this.logLevel}] ${message}`);}}
// app.module.ts providers:[{ provide:LOG_LEVEL, useValue:'DEBUG'}]

5. 路由 (Routing)

Angular Router 用于实现单页应用的路由导航。

示例:基础路由配置
// app-routing.module.tsimport{ NgModule }from'@angular/core';import{ RouterModule, Routes }from'@angular/router';import{ HomeComponent }from'./home/home.component';import{ UserListComponent }from'./user/user-list.component';import{ UserDetailComponent }from'./user/user-detail.component';import{ NotFoundComponent }from'./not-found/not-found.component';const routes: Routes =[{ path:'', redirectTo:'/home', pathMatch:'full'},{ path:'home', component: HomeComponent },{ path:'users', component: UserListComponent },{ path:'users/:id', component: UserDetailComponent },{ path:'**', component: NotFoundComponent }];@NgModule({ imports:[RouterModule.forRoot(routes)], exports:[RouterModule]})exportclassAppRoutingModule{}
示例:路由守卫
// auth.guard.tsimport{ Injectable }from'@angular/core';import{ CanActivate, Router }from'@angular/router';import{ AuthService }from'./auth.service';@Injectable({ providedIn:'root'})exportclassAuthGuardimplementsCanActivate{constructor(private authService: AuthService,private router: Router ){}canActivate():boolean{if(this.authService.isAuthenticated()){returntrue;}else{this.router.navigate(['/login']);returnfalse;}}}
// 在路由中使用守卫const routes: Routes =[{ path:'dashboard', component: DashboardComponent, canActivate:[AuthGuard]}];
示例:路由参数和查询参数
// user-detail.component.tsimport{ Component, OnInit }from'@angular/core';import{ ActivatedRoute, Router }from'@angular/router';@Component({ selector:'app-user-detail', template:` <div> <h2>用户详情</h2> <p>ID: {{ userId }}</p> <p>模式: {{ mode }}</p> <button (click)="goBack()">返回</button> </div> `})exportclassUserDetailComponentimplementsOnInit{ userId!:number; mode!:string;constructor(private route: ActivatedRoute,private router: Router ){}ngOnInit(){// 获取路由参数this.userId =+this.route.snapshot.paramMap.get('id')!;// 获取查询参数this.mode =this.route.snapshot.queryParamMap.get('mode')||'view';// 监听参数变化this.route.paramMap.subscribe(params =>{this.userId =+params.get('id')!;});}goBack(){this.router.navigate(['/users']);}}

6. 数据绑定 (Data Binding)

Angular 支持多种数据绑定方式。

示例:插值绑定
<!-- 显示组件属性 --><h1>{{ title }}</h1><p>当前时间: {{ getCurrentTime() }}</p>
示例:属性绑定
<!-- 绑定 HTML 属性 --><img[src]="imageUrl"[alt]="imageAlt"><!-- 绑定 DOM 属性 --><button[disabled]="isDisabled">提交</button><!-- 绑定类 --><div[class.active]="isActive"[class.error]="hasError"></div><!-- 绑定样式 --><div[style.color]="textColor"[style.font-size.px]="fontSize"></div>
示例:事件绑定
<!-- 点击事件 --><button(click)="handleClick()">点击</button><!-- 带事件对象 --><button(click)="handleClick($event)">点击</button><!-- 输入事件 --><input(input)="onInput($event)"(keyup.enter)="onEnter()">
示例:双向绑定
// component.tsexportclassFormComponent{ username =''; email ='';}
<!-- 使用 ngModel 双向绑定 --><input[(ngModel)]="username"placeholder="用户名"><input[(ngModel)]="email"type="email"placeholder="邮箱"><!-- 等价写法 --><input[ngModel]="username"(ngModelChange)="username = $event">

7. 指令 (Directives)

指令用于扩展 HTML 元素的功能。

示例:结构型指令
<!-- *ngIf - 条件渲染 --><div*ngIf="isLoggedIn">欢迎回来!</div><div*ngIf="!isLoggedIn">请登录</div><!-- *ngFor - 列表渲染 --><ul><li*ngFor="let user of users; let i = index; let first = first"> {{ i + 1 }}. {{ user.name }} <span*ngIf="first">(第一个)</span></li></ul><!-- *ngSwitch - 多条件判断 --><div[ngSwitch]="status"><p*ngSwitchCase="'loading'">加载中...</p><p*ngSwitchCase="'success'">成功!</p><p*ngSwitchCase="'error'">错误!</p><p*ngSwitchDefault>未知状态</p></div>
示例:属性型指令
// highlight.directive.tsimport{ Directive, ElementRef, Input, Renderer2, OnInit }from'@angular/core';@Directive({ selector:'[appHighlight]'})exportclassHighlightDirectiveimplementsOnInit{@Input() appHighlight ='yellow';@Input() defaultColor ='transparent';constructor(private el: ElementRef,private renderer: Renderer2 ){}ngOnInit(){this.setBackgroundColor(this.appHighlight ||this.defaultColor);}privatesetBackgroundColor(color:string){this.renderer.setStyle(this.el.nativeElement,'background-color', color);}}
<!-- 使用自定义指令 --><pappHighlight="yellow">高亮文本</p><p[appHighlight]="highlightColor">动态高亮</p>
示例:结构型指令(自定义)
// unless.directive.tsimport{ Directive, Input, TemplateRef, ViewContainerRef }from'@angular/core';@Directive({ selector:'[appUnless]'})exportclassUnlessDirective{private hasView =false;constructor(private templateRef: TemplateRef<any>,private viewContainer: ViewContainerRef ){}@Input()setappUnless(condition:boolean){if(!condition &&!this.hasView){this.viewContainer.createEmbeddedView(this.templateRef);this.hasView =true;}elseif(condition &&this.hasView){this.viewContainer.clear();this.hasView =false;}}}
<!-- 使用自定义结构型指令 --><div*appUnless="isHidden">这段内容在 isHidden 为 false 时显示</div>

8. 管道 (Pipes)

管道用于转换数据显示格式。

示例:内置管道
<!-- 日期管道 --><p>{{ today | date:'yyyy-MM-dd' }}</p><p>{{ today | date:'full' }}</p><!-- 货币管道 --><p>{{ price | currency:'CNY':'symbol':'1.2-2' }}</p><!-- 数字管道 --><p>{{ number | number:'1.2-2' }}</p><!-- 百分比管道 --><p>{{ ratio | percent:'1.2-2' }}</p><!-- 大写/小写管道 --><p>{{ text | uppercase }}</p><p>{{ text | lowercase }}</p><!-- 切片管道 --><p>{{ longText | slice:0:100 }}...</p><!-- JSON 管道 --><pre>{{ object | json }}</pre>
示例:自定义管道
// truncate.pipe.tsimport{ Pipe, PipeTransform }from'@angular/core';@Pipe({ name:'truncate'})exportclassTruncatePipeimplementsPipeTransform{transform(value:string, limit:number=20, trail:string='...'):string{if(!value)return'';return value.length > limit ? value.substring(0, limit)+ trail : value;}}
// filter.pipe.tsimport{ Pipe, PipeTransform }from'@angular/core';@Pipe({ name:'filter', pure:false// 非纯管道,每次变更检测都会执行})exportclassFilterPipeimplementsPipeTransform{transform(items:any[], searchText:string):any[]{if(!items)return[];if(!searchText)return items; searchText = searchText.toLowerCase();return items.filter(item => item.name.toLowerCase().includes(searchText));}}
<!-- 使用自定义管道 --><p>{{ longText | truncate:50 }}</p><div*ngFor="let item of items | filter:searchText"> {{ item.name }} </div>

9. HTTP 客户端

Angular HttpClient 用于发送 HTTP 请求。

示例:GET 请求
// user.service.tsimport{ HttpClient, HttpParams }from'@angular/common/http';import{ Observable }from'rxjs';@Injectable({ providedIn:'root'})exportclassUserService{private apiUrl ='https://api.example.com/users';constructor(private http: HttpClient){}// 简单 GET 请求getUsers(): Observable<User[]>{returnthis.http.get<User[]>(this.apiUrl);}// 带查询参数的 GET 请求searchUsers(keyword:string, page:number=1): Observable<User[]>{const params =newHttpParams().set('keyword', keyword).set('page', page.toString());returnthis.http.get<User[]>(this.apiUrl,{ params });}// 带响应类型的 GET 请求downloadFile(): Observable<Blob>{returnthis.http.get(this.apiUrl +'/export',{ responseType:'blob'});}}
示例:POST/PUT/DELETE 请求
// user.service.tscreateUser(user: User): Observable<User>{returnthis.http.post<User>(this.apiUrl, user);}updateUser(id:number, user: Partial<User>): Observable<User>{returnthis.http.put<User>(`${this.apiUrl}/${id}`, user);}deleteUser(id:number): Observable<void>{returnthis.http.delete<void>(`${this.apiUrl}/${id}`);}
示例:HTTP 拦截器
// auth.interceptor.tsimport{ Injectable }from'@angular/core';import{ HttpRequest, HttpHandler, HttpEvent, HttpInterceptor }from'@angular/common/http';import{ Observable }from'rxjs';@Injectable()exportclassAuthInterceptorimplementsHttpInterceptor{intercept( request: HttpRequest<any>, next: HttpHandler ): Observable<HttpEvent<any>>{// 添加认证 tokenconst token = localStorage.getItem('token');if(token){ request = request.clone({ setHeaders:{ Authorization:`Bearer ${token}`}});}return next.handle(request);}}
// app.module.tsimport{HTTP_INTERCEPTORS}from'@angular/common/http'; providers:[{ provide:HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi:true}]
示例:错误处理
// user.service.tsimport{ catchError, retry }from'rxjs/operators';import{ throwError }from'rxjs';getUsers(): Observable<User[]>{returnthis.http.get<User[]>(this.apiUrl).pipe(retry(3),// 重试 3 次catchError(this.handleError));}privatehandleError(error:any){let errorMessage ='发生未知错误';if(error.error instanceofErrorEvent){ errorMessage =`错误: ${error.error.message}`;}else{ errorMessage =`错误代码: ${error.status}\n消息: ${error.message}`;}console.error(errorMessage);returnthrowError(()=> errorMessage);}

10. 表单 (Forms)

Angular 提供两种表单方式:模板驱动表单和响应式表单。

示例:模板驱动表单
// login.component.tsimport{ Component }from'@angular/core';@Component({ selector:'app-login', template:` <form #loginForm="ngForm" (ngSubmit)="onSubmit(loginForm)"> <div> <label>用户名:</label> <input name="username" ngModel required minlength="3" #username="ngModel"> <div *ngIf="username.invalid && username.touched"> <span *ngIf="username.errors?.['required']">用户名必填</span> <span *ngIf="username.errors?.['minlength']">至少3个字符</span> </div> </div> <div> <label>密码:</label> <input type="password" name="password" ngModel required> </div> <button type="submit" [disabled]="loginForm.invalid"> 登录 </button> </form> `})exportclassLoginComponent{onSubmit(form:any){if(form.valid){console.log('表单数据:', form.value);}}}
示例:响应式表单
// register.component.tsimport{ Component, OnInit }from'@angular/core';import{ FormBuilder, FormGroup, Validators, AbstractControl }from'@angular/forms';@Component({ selector:'app-register', template:` <form [formGroup]="registerForm" (ngSubmit)="onSubmit()"> <div> <label>邮箱:</label> <input formControlName="email"> <div *ngIf="email.invalid && email.touched"> <span *ngIf="email.errors?.['required']">邮箱必填</span> <span *ngIf="email.errors?.['email']">邮箱格式不正确</span> </div> </div> <div> <label>密码:</label> <input type="password" formControlName="password"> </div> <div> <label>确认密码:</label> <input type="password" formControlName="confirmPassword"> <div *ngIf="registerForm.errors?.['passwordMismatch']"> 密码不匹配 </div> </div> <button type="submit" [disabled]="registerForm.invalid"> 注册 </button> </form> `})exportclassRegisterComponentimplementsOnInit{ registerForm!: FormGroup;constructor(private fb: FormBuilder){}ngOnInit(){this.registerForm =this.fb.group({ email:['',[Validators.required, Validators.email]], password:['',[Validators.required, Validators.minLength(6)]], confirmPassword:['']},{ validators:this.passwordMatchValidator });}getemail(){returnthis.registerForm.get('email')!;}getpassword(){returnthis.registerForm.get('password')!;}getconfirmPassword(){returnthis.registerForm.get('confirmPassword')!;}passwordMatchValidator(control: AbstractControl){const password = control.get('password');const confirmPassword = control.get('confirmPassword');if(password && confirmPassword && password.value !== confirmPassword.value){return{ passwordMismatch:true};}returnnull;}onSubmit(){if(this.registerForm.valid){console.log('表单数据:',this.registerForm.value);}}}
示例:动态表单
// dynamic-form.component.tsimport{ Component }from'@angular/core';import{ FormArray, FormBuilder, FormGroup, Validators }from'@angular/forms';@Component({ selector:'app-dynamic-form', template:` <form [formGroup]="form"> <div formArrayName="hobbies"> <div *ngFor="let hobby of hobbies.controls; let i = index" [formGroupName]="i"> <input formControlName="name" placeholder="爱好名称"> <button type="button" (click)="removeHobby(i)">删除</button> </div> </div> <button type="button" (click)="addHobby()">添加爱好</button> </form> `})exportclassDynamicFormComponent{ form!: FormGroup;constructor(private fb: FormBuilder){this.form =this.fb.group({ hobbies:this.fb.array([])});}gethobbies(){returnthis.form.get('hobbies')as FormArray;}addHobby(){const hobbyGroup =this.fb.group({ name:['', Validators.required]});this.hobbies.push(hobbyGroup);}removeHobby(index:number){this.hobbies.removeAt(index);}}

11. 生命周期钩子 (Lifecycle Hooks)

组件生命周期钩子允许在组件生命周期的特定时刻执行代码。

Angular 组件生命周期(常用顺序与作用):

  1. constructor
    注入依赖,尽量不做复杂逻辑,不访问输入属性。
  2. ngOnChanges(changes: SimpleChanges)
    输入属性 @Input 变更时触发;首次也会触发。可根据 changes 做差异化处理。
  3. ngOnInit
    初始化时机,适合发起首次请求、初始化数据;此时可安全读取 @Input。
  4. ngDoCheck
    自定义变更检测钩子,谨慎使用,避免重计算导致性能问题。
  5. ngAfterContentInit / ngAfterContentChecked
    针对内容投影()的初始化/变更检查。
  6. ngAfterViewInit / ngAfterViewChecked
    视图(模板、子组件)初始化/变更后触发;此时可安全访问 @ViewChild/@ViewChildren。
  7. ngOnDestroy
    销毁前清理:取消订阅、清除计时器/监听、销毁资源。
    常用实践:
    数据初始化:放 ngOnInit。
    监听输入变化:用 ngOnChanges 或 @Input() set …。
    访问子组件/DOM:放 ngAfterViewInit。
    取消订阅:在 ngOnDestroy 里统一清理(如 takeUntil/Subscription.unsubscribe)。
示例:完整生命周期
// lifecycle.component.tsimport{ Component, OnInit, OnChanges, OnDestroy, AfterViewInit, AfterViewChecked, AfterContentInit, AfterContentChecked, DoCheck, Input, SimpleChanges }from'@angular/core';@Component({ selector:'app-lifecycle', template:'<div>{{ message }}</div>'})exportclassLifecycleComponentimplementsOnInit, OnChanges, DoCheck, AfterContentInit, AfterContentChecked, AfterViewInit, AfterViewChecked, OnDestroy {@Input() message ='';constructor(){console.log('1. constructor');}ngOnChanges(changes: SimpleChanges){console.log('2. ngOnChanges', changes);}ngOnInit(){console.log('3. ngOnInit');}ngDoCheck(){console.log('4. ngDoCheck');}ngAfterContentInit(){console.log('5. ngAfterContentInit');}ngAfterContentChecked(){console.log('6. ngAfterContentChecked');}ngAfterViewInit(){console.log('7. ngAfterViewInit');}ngAfterViewChecked(){console.log('8. ngAfterViewChecked');}ngOnDestroy(){console.log('9. ngOnDestroy - 清理资源');}}
示例:使用 ViewChild 和 AfterViewInit
// component.tsimport{ Component, ViewChild, AfterViewInit, ElementRef }from'@angular/core';@Component({ selector:'app-example', template:` <div #myDiv>内容</div> <app-child #child></app-child> `})exportclassExampleComponentimplementsAfterViewInit{@ViewChild('myDiv') myDiv!: ElementRef;@ViewChild('child') childComponent!: ChildComponent;ngAfterViewInit(){// 此时可以安全访问子组件和 DOM 元素console.log(this.myDiv.nativeElement.textContent);this.childComponent.doSomething();}}

12. RxJS 和 Observable

RxJS 是 Angular 中处理异步操作的核心库。

示例:基础 Observable
import{ Observable,of, from }from'rxjs';// 创建简单的 Observableconst simple$ =of(1,2,3); simple$.subscribe(value =>console.log(value));// 从数组创建const array$ =from([1,2,3]); array$.subscribe(value =>console.log(value));// 从 Promise 创建const promise$ =from(fetch('/api/data')); promise$.subscribe(response =>console.log(response));
示例:常用操作符
import{ map, filter, tap, catchError, switchMap, debounceTime }from'rxjs/operators';// map - 转换数据this.http.get<User[]>('/api/users').pipe(map(users => users.map(user => user.name))).subscribe(names =>console.log(names));// filter - 过滤数据this.http.get<User[]>('/api/users').pipe(filter(users => users.length >0)).subscribe(users =>console.log(users));// tap - 执行副作用操作this.http.get<User[]>('/api/users').pipe(tap(users =>console.log('获取到用户:', users))).subscribe();// switchMap - 切换 Observablethis.searchControl.valueChanges.pipe(debounceTime(300),switchMap(keyword =>this.searchUsers(keyword))).subscribe(results =>console.log(results));// catchError - 错误处理this.http.get<User[]>('/api/users').pipe(catchError(error =>{console.error('错误:', error);returnof([]);// 返回默认值})).subscribe();
示例:Subject 和 BehaviorSubject
import{ Subject, BehaviorSubject }from'rxjs';// Subject - 多播 ObservableexportclassMessageService{private messageSubject =newSubject<string>();public messages$ =this.messageSubject.asObservable();sendMessage(message:string){this.messageSubject.next(message);}}// BehaviorSubject - 带初始值的 SubjectexportclassStateService{private stateSubject =newBehaviorSubject<number>(0);public state$ =this.stateSubject.asObservable();updateState(value:number){this.stateSubject.next(value);}getCurrentState():number{returnthis.stateSubject.value;}}
示例:取消订阅
import{ Component, OnDestroy }from'@angular/core';import{ Subscription }from'rxjs';@Component({ selector:'app-example', template:'<div>{{ data }}</div>'})exportclassExampleComponentimplementsOnDestroy{ data:any;private subscription =newSubscription();ngOnInit(){// 方式1: 使用 Subscriptionconst sub1 =this.service.getData().subscribe(data =>{this.data = data;});this.subscription.add(sub1);// 方式2: 使用 takeUntilthis.service.getData().pipe(takeUntil(this.destroy$)).subscribe(data =>{this.data = data;});}ngOnDestroy(){this.subscription.unsubscribe();}}

13. 状态管理

示例:使用 Service 进行状态管理
// cart.service.tsimport{ Injectable }from'@angular/core';import{ BehaviorSubject, Observable }from'rxjs';exportinterfaceCartItem{ id:number; name:string; price:number; quantity:number;}@Injectable({ providedIn:'root'})exportclassCartService{private cartSubject =newBehaviorSubject<CartItem[]>([]);public cart$ =this.cartSubject.asObservable();getCart(): Observable<CartItem[]>{returnthis.cart$;}addItem(item: CartItem){const current =this.cartSubject.value;const existing = current.find(i => i.id === item.id);if(existing){ existing.quantity += item.quantity;}else{ current.push(item);}this.cartSubject.next([...current]);}removeItem(id:number){const current =this.cartSubject.value.filter(item => item.id !== id);this.cartSubject.next(current);}clearCart(){this.cartSubject.next([]);}getTotal():number{returnthis.cartSubject.value.reduce((sum, item)=> sum + item.price * item.quantity,0);}}
示例:使用 NgRx(状态管理库)
// cart.actions.tsimport{ createAction, props }from'@ngrx/store';import{ CartItem }from'./cart.model';exportconst addItem =createAction('[Cart] Add Item',props<{ item: CartItem }>());exportconst removeItem =createAction('[Cart] Remove Item',props<{ id:number}>());exportconst clearCart =createAction('[Cart] Clear');
// cart.reducer.tsimport{ createReducer, on }from'@ngrx/store';import{ addItem, removeItem, clearCart }from'./cart.actions';import{ CartItem }from'./cart.model';exportinterfaceCartState{ items: CartItem[];}exportconst initialState: CartState ={ items:[]};exportconst cartReducer =createReducer( initialState,on(addItem,(state,{ item })=>{const existing = state.items.find(i => i.id === item.id);if(existing){return{...state, items: state.items.map(i => i.id === item.id ?{...i, quantity: i.quantity + item.quantity }: i )};}return{...state, items:[...state.items, item]};}),on(removeItem,(state,{ id })=>({...state, items: state.items.filter(item => item.id !== id)})),on(clearCart, state =>({...state, items:[]})));
// component.tsimport{ Component }from'@angular/core';import{ Store }from'@ngrx/store';import{ Observable }from'rxjs';import{ addItem }from'./cart.actions';import{ CartState }from'./cart.reducer';@Component({ selector:'app-cart', template:` <div *ngFor="let item of items$ | async"> {{ item.name }} - {{ item.price }} </div> `})exportclassCartComponent{ items$: Observable<CartItem[]>;constructor(private store: Store<{ cart: CartState }>){this.items$ =this.store.select(state => state.cart.items);}addToCart(item: CartItem){this.store.dispatch(addItem({ item }));}}

14. 测试

示例:组件测试
// app.component.spec.tsimport{ TestBed }from'@angular/core/testing';import{ AppComponent }from'./app.component';describe('AppComponent',()=>{beforeEach(async()=>{await TestBed.configureTestingModule({ declarations:[AppComponent]}).compileComponents();});it('should create the app',()=>{const fixture = TestBed.createComponent(AppComponent);const app = fixture.componentInstance;expect(app).toBeTruthy();});it('should increment count',()=>{const fixture = TestBed.createComponent(AppComponent);const component = fixture.componentInstance;const initialCount = component.count; component.increment();expect(component.count).toBe(initialCount +1);});it('should render title',()=>{const fixture = TestBed.createComponent(AppComponent); fixture.detectChanges();const compiled = fixture.nativeElement;expect(compiled.querySelector('h1').textContent).toContain('我的 Angular 应用');});});
示例:服务测试
// user.service.spec.tsimport{ TestBed }from'@angular/core/testing';import{ HttpClientTestingModule, HttpTestingController }from'@angular/common/http/testing';import{ UserService }from'./user.service';describe('UserService',()=>{let service: UserService;let httpMock: HttpTestingController;beforeEach(()=>{ TestBed.configureTestingModule({ imports:[HttpClientTestingModule], providers:[UserService]}); service = TestBed.inject(UserService); httpMock = TestBed.inject(HttpTestingController);});afterEach(()=>{ httpMock.verify();});it('should fetch users',()=>{const mockUsers =[{ id:1, name:'张三', email:'[email protected]'},{ id:2, name:'李四', email:'[email protected]'}]; service.getUsers().subscribe(users =>{expect(users.length).toBe(2);expect(users).toEqual(mockUsers);});const req = httpMock.expectOne('/api/users');expect(req.request.method).toBe('GET'); req.flush(mockUsers);});});

总结

Angular 是一个功能强大的前端框架,主要特点包括:

  1. 组件化架构 - 可复用的组件系统
  2. 依赖注入 - 自动管理依赖关系
  3. 模块化 - 组织代码结构
  4. 路由系统 - 单页应用导航
  5. 响应式编程 - RxJS 处理异步操作
  6. 双向数据绑定 - 简化数据流
  7. 指令系统 - 扩展 HTML 功能
  8. 表单处理 - 强大的表单验证
  9. HTTP 客户端 - 处理 API 请求
  10. 测试支持 - 完整的测试工具

这些特性使得 Angular 非常适合构建大型、复杂的企业级应用。

下边是Angular项目结构示例

my-angular-app/
├─ angular.json # Angular CLI 配置
├─ package.json # 项目依赖与脚本
├─ tsconfig.json # TypeScript 编译配置
├─ tsconfig.app.json # 应用 TS 配置
├─ tsconfig.spec.json # 测试 TS 配置
├─ karma.conf.js # 单元测试(Karma)配置
├─ src/
│ ├─ main.ts # 应用入口(bootstrap AppModule)
│ ├─ index.html # 单页应用入口 HTML
│ ├─ styles.scss # 全局样式
│ ├─ polyfills.ts # 兼容性填充
│ ├─ environments/ # 环境变量(prod/dev)
│ │ ├─ environment.ts
│ │ └─ environment.prod.ts
│ ├─ app/
│ │ ├─ app.module.ts # 根模块
│ │ ├─ app.component.* # 根组件
│ │ ├─ core/ # 核心服务、拦截器、守卫(全局单例)
│ │ ├─ shared/ # 可复用组件、指令、管道、工具
│ │ ├─ features/ # 业务功能模块(按域拆分)
│ │ │ ├─ home/ # 示例功能模块
│ │ │ ├─ users/ # 示例功能模块
│ │ │ └─ … # 其它业务域
│ │ ├─ services/ #(可选)跨功能通用服务
│ │ ├─ models/ #(可选)接口/类型定义
│ │ ├─ guards/ #(可选)路由守卫
│ │ ├─ interceptors/ #(可选)HTTP 拦截器
│ │ ├─ store/ #(可选)状态管理(NgRx、Akita 等)
│ │ └─ app-routing.module.ts # 根路由
│ └─ assets/ # 静态资源(图片、字体、i18n 等)
└─ e2e/ # 端到端测试(如使用 Cypress/Protractor)

目录

  1. Angular 完整教程 - 核心内容详解
  2. 目录
  3. 1\. 组件 (Components)
  4. 示例:基础组件
  5. 示例:带输入输出的组件
  6. 2\. 模块 (Modules)
  7. 示例:根模块
  8. 示例:功能模块
  9. 3\. 服务 (Services)
  10. 示例:基础服务
  11. 示例:带缓存的服务
  12. 4\. 依赖注入 (Dependency Injection)
  13. 示例:构造函数注入
  14. 示例:可选依赖和注入令牌
  15. 5\. 路由 (Routing)
  16. 示例:基础路由配置
  17. 示例:路由守卫
  18. 示例:路由参数和查询参数
  19. 6\. 数据绑定 (Data Binding)
  20. 示例:插值绑定
  21. 示例:属性绑定
  22. 示例:事件绑定
  23. 示例:双向绑定
  24. 7\. 指令 (Directives)
  25. 示例:结构型指令
  26. 示例:属性型指令
  27. 示例:结构型指令(自定义)
  28. 8\. 管道 (Pipes)
  29. 示例:内置管道
  30. 示例:自定义管道
  31. 9\. HTTP 客户端
  32. 示例:GET 请求
  33. 示例:POST/PUT/DELETE 请求
  34. 示例:HTTP 拦截器
  35. 示例:错误处理
  36. 10\. 表单 (Forms)
  37. 示例:模板驱动表单
  38. 示例:响应式表单
  39. 示例:动态表单
  40. 11\. 生命周期钩子 (Lifecycle Hooks)
  41. 示例:完整生命周期
  42. 示例:使用 ViewChild 和 AfterViewInit
  43. 12\. RxJS 和 Observable
  44. 示例:基础 Observable
  45. 示例:常用操作符
  46. 示例:Subject 和 BehaviorSubject
  47. 示例:取消订阅
  48. 13\. 状态管理
  49. 示例:使用 Service 进行状态管理
  50. 示例:使用 NgRx(状态管理库)
  51. 14\. 测试
  52. 示例:组件测试
  53. 示例:服务测试
  54. 总结

更多推荐文章

查看全部
  • 基于 LLaMA-Factory 和 LoRA 微调 GPT-OSS-20B 模型教程
  • Python 搭建 AI API 对话机器人 UI 程序完整指南
  • 阿里 QoderWork 上线:本地运行、自主规划的 AI 工作搭子
  • JetBrains IDE 中 GitHub Copilot 的进阶使用技巧与实战场景
  • C++核心知识点梳理:类型兼容、多继承与虚基类
  • 基于 Python 的抖音视频批量自动化工具实战指南
  • CFAR 目标检测算法详解(附 MATLAB 示例)
  • AI 辅助编程的边界探索:当 Copilot 学会写测试
  • Python 核心知识体系总结:基础语法、内存模型与面向对象编程
  • 前端高频面试题:TypeScript 核心考点与实战
  • Git 配置 SSH Key 连接 GitHub 详细教程
  • C++ Elasticsearch 第三方库 elasticlient 详解
  • Linux 工程化实战:构建你的第一个命令行工具项目
  • 基于 Java Spring Boot 的高校网络教学系统设计与实现
  • AIGC 技术解析:人工智能生成内容的现状与未来
  • IBM Watson Conversation API 实战:机场客服场景与上下文管理
  • 基于大疆 MSDK 实现的无人机视觉引导自适应降落功能
  • 机器人灵巧手技术演进市场格局与未来前景
  • VRM4U 插件完整指南:在 Unreal Engine 5 中高效处理 VRM 模型
  • MySQL 迁移至金仓数据库的核心兼容性与实操指南

相关免费在线工具

  • curl 转代码

    解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online

  • JSON 压缩

    通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online