跳到主要内容
极客日志极客日志面向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/7/2036K 浏览

@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. 总结
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • SwiftUI 零基础入门指南:快速上手与实战解析
  • Windows 版 nvm 安装配置与 Node.js 多版本管理教程
  • FPGA 与 IC 职业前景对比及选择指南
  • JDK 安装与环境变量配置(Win11 详细版)
  • Python 实现 PDF 表单域的自动化创建与智能填充
  • 大模型新人职业指南:四大方向解析与避坑建议
  • 光伏产品缺陷检测 AI 深度学习算法 (CN118134841A)
  • OpenClaw 安装配置指南:接入 Minimax/DeepSeek 模型与飞书机器人
  • Agent AI 技术原理与工程实践指南
  • DFS/BFS 专项练习:从海岛问题掌握图论基础(C++ 实现)
  • Windows 11 资源管理器增强:QTTabBar 中文优化版安装指南
  • 零改造迁移实录:2000+存储过程从 SQL Server 迁移至 KingbaseES V9R4C12
  • OpenClaw.ai:Agentic AI 时代的 Spring Framework 时刻
  • 使用 ZeroNews 远程管理 OpenClaw Gateway Dashboard
  • MySQL 数据库基础入门:Linux 环境安装与配置
  • WebGL 矩阵变换详解:平移旋转缩放与复合动画
  • Claude Skills 开源工具精选:GitHub 热门 7 大 AI 技能库
  • 默认安全治理实践:水平越权检测与前端安全防控
  • Windows 系统安装与配置 Neo4j 图数据库
  • CSS 基础语法与选择器实战指南

相关免费在线工具

  • 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