【Web前端】Angular核心知识点梳理

1. Angular 架构概述

1.1 核心概念

1)模块化架构 (NgModule)。

2)组件化开发。

3)依赖注入系统。

4)单向数据流。

5)TypeScript 支持。

1.2 平台支持

1)Web 应用 (浏览器)。

2)移动应用 (Ionic + Angular)。

3)桌面应用 (Electron + Angular)。

4)服务端渲染 (Angular Universal)。

2. 模块系统 (NgModule)

2.1 模块定义

TypeScript 复制代码
@NgModule({
  declarations: [AppComponent, UserComponent], // 组件、指令、管道
  imports: [BrowserModule, HttpClientModule], // 导入其他模块
  providers: [UserService, AuthService],     // 服务提供者
  bootstrap: [AppComponent]                  // 根组件
})
export class AppModule { }

2.2 模块类型

1)根模块 (AppModule)

2)特性模块 (FeatureModule)

3)共享模块 (SharedModule)

4)核心模块 (CoreModule)

5)路由模块 (RoutingModule)

3. 组件系统

3.1 组件结构

TypeScript 复制代码
@Component({
  selector: 'app-user',
  template: `<h1>{{user.name}}</h1>`,
  styleUrls: ['./user.component.css'],
  providers: [UserService]
})
export class UserComponent implements OnInit {
  @Input() user: User;
  @Output() userSelected = new EventEmitter<User>();
  
  constructor(private userService: UserService) {}
  
  ngOnInit(): void {
    // 初始化逻辑
  }
}

3.2 组件生命周期钩子

TypeScript 复制代码
export class UserComponent implements 
  OnInit,        // 初始化
  OnDestroy,     // 销毁
  OnChanges,     // 输入属性变化
  AfterViewInit, // 视图初始化后
  AfterContentInit // 内容投影后
{
  ngOnInit() { /* 组件初始化 */ }
  ngOnChanges(changes: SimpleChanges) { /* 输入属性变化 */ }
  ngAfterViewInit() { /* 视图初始化后 */ }
  ngOnDestroy() { /* 组件销毁前清理 */ }
}

3.3 视图封装模式

1)Emulated (默认): 样式封装。

2)Native: 使用 Shadow DOM。

3)None: 全局样式。

4. 模板与数据绑定

4.1 数据绑定类型

html 复制代码
<!-- 插值 -->
<h1>{{title}}</h1>

<!-- 属性绑定 -->
<img [src]="imageUrl" [alt]="description">

<!-- 事件绑定 -->
<button (click)="onSave()">保存</button>

<!-- 双向绑定 -->
<input [(ngModel)]="userName">

<!-- 样式绑定 -->
<div [class.active]="isActive" [style.color]="textColor">

4.2 内置指令

html 复制代码
<!-- 结构指令 -->
<div *ngIf="isVisible">条件显示</div>
<li *ngFor="let item of items">{{item.name}}</li>
<div [ngSwitch]="status">
  <span *ngSwitchCase="'active'">活跃</span>
  <span *ngSwitchDefault>非活跃</span>
</div>

<!-- 属性指令 -->
<div [ngClass]="{'active': isActive, 'disabled': isDisabled}">
<div [ngStyle]="{'font-size': fontSize + 'px'}">
<div [ngModel]="value" (ngModelChange)="onChange($event)">

4.3 模板引用变量

html 复制代码
<input #emailInput type="email">
<button (click)="validate(emailInput.value)">验证</button>

5. 服务与依赖注入

5.1 服务创建

TypeScript 复制代码
@Injectable({
  providedIn: 'root' // 根注入器
})
export class UserService {
  private apiUrl = '/api/users';
  
  constructor(private http: HttpClient) {}
  
  getUsers(): Observable<User[]> {
    return this.http.get<User[]>(this.apiUrl);
  }
}

5.2 依赖注入层次

1)根注入器 (全局单例)。

2)模块注入器 (模块级别)。

3)组件注入器 (组件级别)。

5.3 注入令牌

TypeScript 复制代码
// 字符串令牌
export const API_URL = new InjectionToken<string>('api.url');

// 在模块中提供
providers: [{ provide: API_URL, useValue: 'https://api.example.com' }]

// 在服务中注入
constructor(@Inject(API_URL) private apiUrl: string) {}

6. 路由系统

6.1 路由配置

TypeScript 复制代码
const routes: Routes = [
  { path: '', component: HomeComponent },
  { path: 'users', component: UserListComponent },
  { path: 'users/:id', component: UserDetailComponent },
  { path: 'admin', loadChildren: () => import('./admin/admin.module').then(m => m.AdminModule) },
  { path: '**', component: PageNotFoundComponent }
];

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

6.2 路由导航

TypeScript 复制代码
export class UserComponent {
  constructor(private router: Router, private route: ActivatedRoute) {}
  
  navigateToUser(id: number) {
    // 编程式导航
    this.router.navigate(['/users', id]);
    
    // 带参数导航
    this.router.navigate(['/users'], { queryParams: { page: 1 } });
  }
  
  ngOnInit() {
    // 获取路由参数
    this.route.params.subscribe(params => {
      this.userId = params['id'];
    });
  }
}

6.3 路由守卫

TypeScript 复制代码
@Injectable()
export class AuthGuard implements CanActivate {
  constructor(private authService: AuthService, private router: Router) {}
  
  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
    if (this.authService.isLoggedIn()) {
      return true;
    } else {
      this.router.navigate(['/login']);
      return false;
    }
  }
}

7. 表单处理

7.1 模板驱动表单

html 复制代码
<form #userForm="ngForm" (ngSubmit)="onSubmit(userForm)">
  <input 
    name="username" 
    ngModel 
    #username="ngModel"
    required 
    minlength="3">
  
  <div *ngIf="username.invalid && username.touched">
    <div *ngIf="username.errors?.['required']">用户名必填</div>
    <div *ngIf="username.errors?.['minlength']">用户名至少3位</div>
  </div>
  
  <button type="submit" [disabled]="userForm.invalid">提交</button>
</form>

7.2 响应式表单

TypeScript 复制代码
export class UserFormComponent {
  userForm = new FormGroup({
    username: new FormControl('', [Validators.required, Validators.minLength(3)]),
    email: new FormControl('', [Validators.required, Validators.email]),
    address: new FormGroup({
      street: new FormControl(''),
      city: new FormControl('')
    })
  });
  
  onSubmit() {
    if (this.userForm.valid) {
      console.log(this.userForm.value);
    }
  }
  
  // 在模板中使用
  // <form [formGroup]="userForm" (ngSubmit)="onSubmit()">
  //   <input formControlName="username">
  // </form>
}

8. HTTP 客户端

8.1 HTTP 服务

TypeScript 复制代码
@Injectable()
export class DataService {
  constructor(private http: HttpClient) {}
  
  // GET 请求
  getUsers(): Observable<User[]> {
    return this.http.get<User[]>('/api/users');
  }
  
  // POST 请求
  createUser(user: User): Observable<User> {
    return this.http.post<User>('/api/users', user);
  }
  
  // 带选项的请求
  searchUsers(term: string): Observable<User[]> {
    const options = {
      params: new HttpParams().set('search', term)
    };
    return this.http.get<User[]>('/api/users/search', options);
  }
}

8.2 错误处理

TypeScript 复制代码
getUsers(): Observable<User[]> {
  return this.http.get<User[]>('/api/users').pipe(
    catchError(this.handleError)
  );
}

private handleError(error: HttpErrorResponse) {
  if (error.error instanceof ErrorEvent) {
    // 客户端错误
    console.error('客户端错误:', error.error.message);
  } else {
    // 服务端错误
    console.error(`服务端错误 ${error.status}: ${error.error}`);
  }
  return throwError('发生错误,请重试');
}

9. 状态管理

9.1 服务状态管理

TypeScript 复制代码
@Injectable({ providedIn: 'root' })
export class UserStore {
  private users = new BehaviorSubject<User[]>([]);
  private loading = new BehaviorSubject<boolean>(false);
  
  users$ = this.users.asObservable();
  loading$ = this.loading.asObservable();
  
  loadUsers() {
    this.loading.next(true);
    this.userService.getUsers().subscribe(users => {
      this.users.next(users);
      this.loading.next(false);
    });
  }
}

9.2 NgRx 状态管理 (可选)

TypeScript 复制代码
// Action
export const loadUsers = createAction('[User] Load Users');
export const loadUsersSuccess = createAction(
  '[User] Load Users Success',
  props<{ users: User[] }>()
);

// Reducer
export const userReducer = createReducer(
  initialState,
  on(loadUsers, state => ({ ...state, loading: true })),
  on(loadUsersSuccess, (state, { users }) => ({ 
    ...state, 
    users, 
    loading: false 
  }))
);

// Effect
loadUsers$ = createEffect(() => this.actions$.pipe(
  ofType(loadUsers),
  mergeMap(() => this.userService.getUsers().pipe(
    map(users => loadUsersSuccess({ users })),
    catchError(() => of(loadUsersFailure()))
  ))
));

10. 性能优化

10.1 变更检测策略

TypeScript 复制代码
@Component({
  selector: 'app-user-list',
  templateUrl: './user-list.component.html',
  changeDetection: ChangeDetectionStrategy.OnPush // 使用 OnPush 策略
})
export class UserListComponent {
  @Input() users: User[];
}

10.2 懒加载

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

10.3 跟踪函数

html 复制代码
<div *ngFor="let user of users; trackBy: trackByUserId">
  {{user.name}}
</div>
TypeScript 复制代码
trackByUserId(index: number, user: User): number {
  return user.id;
}

11. 测试

11.1 组件测试

TypeScript 复制代码
describe('UserComponent', () => {
  let component: UserComponent;
  let fixture: ComponentFixture<UserComponent>;
  
  beforeEach(async () => {
    await TestBed.configureTestingModule({
      declarations: [UserComponent],
      imports: [HttpClientTestingModule],
      providers: [UserService]
    }).compileComponents();
  });
  
  beforeEach(() => {
    fixture = TestBed.createComponent(UserComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });
  
  it('应该创建组件', () => {
    expect(component).toBeTruthy();
  });
  
  it('应该显示用户名称', () => {
    component.user = { id: 1, name: '张三' };
    fixture.detectChanges();
    const compiled = fixture.nativeElement;
    expect(compiled.querySelector('h1').textContent).toContain('张三');
  });
});

12. 高级特性

12.1 动态组件

TypeScript 复制代码
export class ModalService {
  constructor(private componentFactoryResolver: ComponentFactoryResolver,
              private injector: Injector) {}
  
  createModal(component: Type<any>): ComponentRef<any> {
    const factory = this.componentFactoryResolver.resolveComponentFactory(component);
    return factory.create(this.injector);
  }
}

12.2 自定义指令

TypeScript 复制代码
@Directive({
  selector: '[appHighlight]'
})
export class HighlightDirective {
  @Input() appHighlight: string;
  
  constructor(private el: ElementRef) {}
  
  @HostListener('mouseenter') onMouseEnter() {
    this.highlight(this.appHighlight || 'yellow');
  }
  
  @HostListener('mouseleave') onMouseLeave() {
    this.highlight(null);
  }
  
  private highlight(color: string) {
    this.el.nativeElement.style.backgroundColor = color;
  }
}

12.3 自定义管道

TypeScript 复制代码
@Pipe({
  name: 'reverse'
})
export class ReversePipe implements PipeTransform {
  transform(value: string): string {
    return value.split('').reverse().join('');
  }
}

13. Angular CLI 重要命令

bash 复制代码
# 创建新项目
ng new my-app

# 生成组件
ng generate component user-list

# 生成服务
ng generate service user

# 生成模块
ng generate module admin

# 构建项目
ng build --prod

# 运行测试
ng test

# 运行端到端测试
ng e2e

14. 总结

Angular 是一个完整的前端框架,具有以下核心特点:

**1)模块化架构:**通过 NgModule 组织代码。

**2)组件化开发:**可复用的 UI 组件。

**3)依赖注入:**强大的服务管理。

**4)TypeScript 支持:**类型安全和更好的开发体验。

**5)强大的工具链:**Angular CLI 提供完整的开发工作流。

**6)丰富的生态系统:**路由、表单、HTTP 等内置功能。

相关推荐
小时前端2 小时前
前端架构师视角:如何设计一个“站稳多端”的跨端体系?
前端·javascript·面试
p***h6432 小时前
JavaScript图像处理开发
开发语言·javascript·图像处理
袅沫2 小时前
Element-UI 番外表格组件
javascript·vue.js·ui
杰克尼2 小时前
vue_day06
前端·javascript·vue.js
DcTbnk2 小时前
ESM (放到打包里 import) 和 IIFE (URL 动态 loadScript)
前端·javascript
狗哥哥2 小时前
从文档到代码:工程化规则体系落地全指南
前端
San302 小时前
深入理解 JavaScript 中的 Symbol:独一无二的值
前端·javascript·ecmascript 6
就叫飞六吧2 小时前
css+js 前端无限画布实现
前端·javascript·css
2501_941148152 小时前
高并发搜索引擎Elasticsearch与Solr深度优化在互联网实践分享
java·开发语言·前端