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>

属性指令

使用 [] 语法,如 ngClassngStyle

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;

子父组件通信

子组件通过 @OutputEventEmitter 向父组件发送数据。

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 中排除 nullundefined
  10. ReturnType<T>: 获取函数类型 T 的返回类型。
  11. InstanceType<T>: 获取构造函数类型 T 的实例类型。

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


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

相关推荐
云端看世界1 分钟前
ECMAScript 类型转换 下
前端·javascript
云端看世界3 分钟前
ECMAScript 运算符怪谈 下
前端·javascript
云端看世界5 分钟前
ECMAScript 函数对象实例化
前端·javascript
前端爆冲5 分钟前
基于vue和flex实现页面可配置组件顺序
前端·javascript·vue.js
云端看世界7 分钟前
ECMAScript 中的特异对象
前端·javascript
il9 分钟前
Deepdive into Tanstack Query - 2.1 QueryClient 基础
前端
_十六11 分钟前
看完就懂!用最简单的方式带你了解 TypeScript 编译器原理
前端·typescript
云端看世界12 分钟前
ECMAScript 运算符怪谈 上
前端·javascript·ecmascript 6
前端涂涂13 分钟前
express的介绍,简单使用
前端
正在脱发中14 分钟前
vue-cropper 遇到的坑 Failed to execute 'getComputedStyle' on 'Window': parameter
前端·vue.js