Angular 开发指南:组件、数据绑定、指令、服务、HTTP、路由和表单

Angular 开发指南:组件、数据绑定、指令、服务、HTTP、路由和表单

在这篇文章中,我们将深入探讨 Angular 开发中的一些核心概念和常用技术,包括组件、数据绑定、指令、服务、HTTP 客户端、路由和表单。通过这些知识,你将能够构建强大和灵活的 Angular 应用程序。


1. 组件 (Components)

Angular 中的组件类似于 Vue 和 React 中的组件。它们是应用的基本构建块,包含模板、样式和逻辑。

组件装饰器

使用 @Component 装饰器定义组件。

typescript 复制代码
import { Component } from '@angular/core';

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

模板

使用 HTML 文件定义组件的模板。

html 复制代码
<h1>{{ title }}</h1>

2. 数据绑定 (Data Binding)

Angular 提供了多种数据绑定方式,包括插值绑定、属性绑定、事件绑定和双向绑定。

插值绑定

使用 {{ }} 语法绑定数据到模板。

html 复制代码
<h1>{{ title }}</h1>

属性绑定

使用 [] 语法绑定属性。

html 复制代码
<img [src]="imageUrl">

事件绑定

使用 () 语法绑定事件。

html 复制代码
<button (click)="handleClick()">Click me</button>

双向绑定

使用 [()] 语法实现双向绑定。

html 复制代码
<input [(ngModel)]="username">

3. 指令 (Directives)

指令是用于操作 DOM 的特殊标记。Angular 提供了结构指令和属性指令。

结构指令

使用 * 语法,如 *ngIf 和 *ngFor。

html 复制代码
<div *ngIf="isVisible">Visible content</div>
<ul>
  <li *ngFor="let item of items">{{ item }}</li>
</ul>

属性指令

使用 [] 语法,如 ngClass 和 ngStyle。

html 复制代码
<div [ngClass]="{'active': isActive}">Styled content</div>

4. 常用 ng 命令

Angular CLI 提供了一系列常用命令来帮助开发者创建、构建、测试和维护 Angular 应用程序。

项目创建和初始化

bash 复制代码
ng new my-app
cd my-app

生成代码

bash 复制代码
ng generate component my-component
ng generate service my-service
ng generate module my-module
ng generate directive my-directive
ng generate pipe my-pipe
ng generate guard my-guard

开发和构建

bash 复制代码
ng serve
ng build
ng build --prod

测试

bash 复制代码
ng test
ng e2e

其他命令

bash 复制代码
ng update
ng version
ng help

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

Angular 提供了一系列生命周期钩子,允许你在组件的不同生命周期阶段执行特定的操作。

  1. ngOnChanges: 当 Angular 设置或重新设置数据绑定输入属性时调用。
  2. ngOnInit: 在 Angular 初始化组件或指令的输入属性之后调用。
  3. ngDoCheck: 在每个变更检测周期中调用。
  4. ngAfterContentInit: 在 Angular 完成组件内容投影之后调用。
  5. ngAfterContentChecked: 在每个变更检测周期之后调用,用于检查内容投影。
  6. ngAfterViewInit: 在 Angular 初始化组件视图及其子视图之后调用。
  7. ngAfterViewChecked: 在每个变更检测周期之后调用,用于检查组件视图及其子视图。
  8. ngOnDestroy: 在 Angular 销毁组件或指令之前调用。

6. 组件通信 (Component Communication)

父子组件通信

父组件通过 [ ] 自定义属性传值,子组件通过 @Input 装饰器接收。

typescript 复制代码
// 父组件
<app-child [data]="parentData"></app-child>

// 子组件
@Input() data: string;

子父组件通信

子组件通过 @Output 和 EventEmitter 向父组件发送数据。

typescript 复制代码
// 子组件
@Output() dataEvent = new EventEmitter<string>();
this.dataEvent.emit('some data');

// 父组件
<app-child (dataEvent)="handleData($event)"></app-child>

同模块组件通信

通过服务进行通信。

typescript 复制代码
constructor(private serviceName: ServiceName)

状态管理库 (NgRx)

使用 NgRx 进行复杂的状态管理。


7. 模板 (Templates)

模板引用变量

使用 # 定义模板引用变量,允许你在模板中引用元素或组件实例。

html 复制代码
<input #inputElement type="text">

结构指令

使用 * 语法,如 *ngIf, *ngFor 等,添加或移除 DOM 元素。

html 复制代码
<div [ngSwitch]="viewMode">
  <p *ngSwitchCase="'map'">Map View</p>
</div>

事件绑定

使用 () 语法绑定事件。

属性绑定

使用 [] 语法绑定属性。

双向绑定

使用 [()] 语法实现双向绑定。


8. 自定义指令 (Custom Directives)

属性指令

typescript 复制代码
import { Directive, ElementRef, Renderer2, HostListener } from '@angular/core';

@Directive({
  selector: '[myDirective]'
})
export class HighlightDirective {
  constructor(private el: ElementRef, private renderer: Renderer2) {}

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

  private highlight(color: string) {
    this.renderer.setStyle(this.el.nativeElement, 'backgroundColor', color);
  }
}

结构指令

typescript 复制代码
import { Directive, TemplateRef, ViewContainerRef, Input } from '@angular/core';

@Directive({
  selector: '[appUnless]'
})
export class UnlessDirective {
  private hasView = false;

  constructor(private templateRef: TemplateRef<any>, private viewContainer: ViewContainerRef) {}

  @Input() set appUnless(condition: boolean) {
    if (!condition && !this.hasView) {
      this.viewContainer.createEmbeddedView(this.templateRef);
      this.hasView = true;
    } else if (condition && this.hasView) {
      this.viewContainer.clear();
      this.hasView = false;
    }
  }
}

9. 服务 (Services)

使用 Angular CLI 创建服务,并使用 @Injectable 装饰器定义服务。

bash 复制代码
ng generate service data
typescript 复制代码
@Injectable({
  providedIn: 'root'
})
export class DataService {
  // 服务代码
}

10. HTTP 客户端 (HTTP Client)

使用 HttpClient 服务进行 HTTP 请求。

typescript 复制代码
import { HttpClient } from '@angular/common/http';

constructor(private http: HttpClient) {}

this.http.get('url').subscribe(data => {
  console.log(data);
});

拦截器 (Interceptors)

typescript 复制代码
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const authToken = 'your-auth-token';
    const authReq = req.clone({
      setHeaders: {
        Authorization: `Bearer ${authToken}`
      }
    });
    return next.handle(authReq);
  }
}

11. 路由 (Routing)

配置路由

在应用程序的根模块中导入 RouterModule 并配置路由。

typescript 复制代码
import { RouterModule, Routes } from '@angular/router';

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

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule {}

路由守卫 (Guards)

创建路由守卫并在路由配置中使用 canActivate 属性来保护路由。

typescript 复制代码
import { CanActivate } from '@angular/router';

@Injectable({
  providedIn: 'root'
})
export class AuthGuard implements CanActivate {
  canActivate(): boolean {
    return true; // Replace with actual authentication check
  }
}

路由参数和查询参数

使用 ActivatedRoute 服务来访问路由参数和查询参数。

typescript 复制代码
import { ActivatedRoute } from '@angular/router';

constructor(private route: ActivatedRoute) {}

ngOnInit() {
  this.route.paramMap.subscribe(params => {
    console.log(params.get('id'));
  });

  this.route.queryParamMap.subscribe(params => {
    console.log(params.get('queryParam'));
  });
}

懒加载模块

使用 NgModule 定义懒加载模块,并在路由配置中使用 loadChildren 属性来按需加载模块。

typescript 复制代码
const routes: Routes = [
  { path: 'lazy', loadChildren: () => import('./lazy/lazy.module').then(m => m.LazyModule) }
];

12. 表单 (Forms)

模板驱动表单

使用 FormsModule 处理模板驱动表单。

typescript 复制代码
import { FormsModule } from '@angular/forms';

@NgModule({
  imports: [FormsModule]
})
export class AppModule {}
html 复制代码
<form #form="ngForm" (ngSubmit)="onSubmit(form)">
  <input name="name" ngModel required>
  <button type="submit">Submit</button>
</form>

响应式表单

使用 ReactiveFormsModule 处理响应式表单。

typescript 复制代码
import { ReactiveFormsModule } from '@angular/forms';

@NgModule({
  imports: [ReactiveFormsModule]
})
export class AppModule {}
typescript 复制代码
import { FormGroup, FormControl, Validators } from '@angular/forms';

this.form = new FormGroup({
  name: new FormControl('', Validators.required)
});
html 复制代码
<form [formGroup]="form" (ngSubmit)="onSubmit()">
  <input formControlName="name">
  <button type="submit">Submit</button>
</form>

表单验证

使用内置验证器和自定义验证器进行表单验证。

typescript 复制代码
import { AbstractControl, ValidatorFn } from '@angular/forms';

export function forbiddenNameValidator(nameRe: RegExp): ValidatorFn {
  return (control: AbstractControl): { [key: string]: any } | null => {
    const forbidden = nameRe.test(control.value);
    return forbidden ? { 'forbiddenName': { value: control.value } } : null;
  };
}

13. TypeScript 高级特性

元组 (Tuple)

元组是一种不可变的数据结构,用于存储一组有序的元素。

typescript 复制代码
let tuple: [number, string] = [1, 'hello'];

条件类型

条件类型根据条件返回不同的类型。

typescript 复制代码
type IsString<T> = T extends string ? true : false;

映射类型

映射类型允许你创建一个新类型,该类型基于另一个类型的所有属性。

typescript 复制代码
type Readonly<T> = {
  readonly [P in keyof T]: T[P];
};

内置实用类型

  1. Partial<T>: 将类型 T 的所有属性变为可选。
  2. Required<T>: 将类型 T 的所有属性变为必填。
  3. Readonly<T>: 将类型 T 的所有属性变为只读。
  4. Pick<T, K>: 从类型 T 中选择一组属性 K,并创建一个新的类型。
  5. Omit<T, K>: 从类型 T 中排除一组属性 K。
  6. Record<K, T>: 将键类型 K 映射到值类型 T。
  7. Exclude<T, U>: 从类型 T 中排除所有可以赋值给类型 U 的属性。
  8. Extract<T, U>: 从类型 T 中提取所有可以赋值给类型 U 的属性。
  9. NonNullable<T>: 从类型 T 中排除 null 和 undefined。
  10. ReturnType<T>: 获取函数类型 T 的返回类型。
  11. InstanceType<T>: 获取构造函数类型 T 的实例类型。

通过理解和掌握这些 Angular 开发中的核心概念和常用技术,你将能够构建强大和灵活的 Angular 应用程序。如果你有任何问题或需要进一步的帮助,请随时提问!


希望这篇文章对你有所帮助!如果你有任何问题或需要进一步的帮助,请随时提问!

相关推荐
卸任10 小时前
Vibe coding工具使用心得
前端·ai编程
brien910 小时前
为什么模型标称 1M,Google Antigravity 聊到 256K 却突然失忆?我们给它做了个原生行内监控圆环
前端
修炼的dance11 小时前
录屏关键帧间隔多少合适?六档实测,2秒到10秒小了75.6%
前端
Lank_M11 小时前
关键帧从1秒拉到10秒,录屏小87.3%,摄像头小10.8%
前端
补码缩写11 小时前
用 ffprobe 拆录屏,八成字节在 29 个关键帧上
前端
百思不得小李11 小时前
一个复杂的动态表单是如何实现的
前端·设计模式
陈随易11 小时前
Cmder 停更 17 个月,2.0 支持 Windows Terminal
前端·后端·程序员
风骏时光牛马11 小时前
前沿视界
前端
kyriewen11 小时前
我扫了 814 个依赖,97 个还敢要 Node 10
前端·javascript·程序员
陈随易12 小时前
3000 万人在用的翻译插件,重写一遍就是一门生意
前端·后端·程序员