Angular 面试题及详细答案

Angular 面试题及详细答案

Angular 作为 Google 维护的企业级前端框架,其面试考察通常覆盖核心概念、生命周期、依赖注入、状态管理、性能优化等维度。以下整理了高频面试题及深度解析,帮助理解原理而非单纯记忆。

一、基础概念与核心特性

1. Angular 和 AngularJS 的主要区别是什么?

Angular(通常指 Angular 2+,简称 Angular)是 AngularJS(Angular 1.x)的完全重写版本,核心差异如下:

对比维度 AngularJS (1.x) Angular (2+)
语言支持 仅支持 JavaScript 推荐 TypeScript(强类型),也支持 JS
架构模式 MVC(Model-View-Controller) 组件化架构(Component-Based)
数据绑定 双向绑定(基于脏检查) 双向绑定(基于 Zone.js)+ 单向绑定([]
依赖注入 模块级注入,配置复杂 层级注入(模块/组件/指令),API 更清晰
性能 脏检查机制,大应用性能差 增量变更检测,性能更优
移动支持 无原生支持,需第三方框架(如 Ionic 1) 原生支持 PWA、移动端适配,可配合 Ionic 4+
生态 老旧,社区活跃度低 活跃,官方维护路由、表单等模块

2. Angular 的核心模块(Modules)有哪些?各自的作用是什么?

Angular 中模块(NgModule)是组织代码的基本单元,每个 Angular 应用至少有一个根模块(AppModule),核心模块分为:

模块名称 作用
BrowserModule 浏览器平台必备模块,提供 ngIfngFor 等内置指令,仅根模块导入。
CommonModule 包含 BrowserModule 的核心指令(无平台相关代码),子模块导入以复用指令。
FormsModule 提供模板驱动表单支持(如 ngModelngForm)。
ReactiveFormsModule 提供响应式表单支持(如 FormGroupFormControl),更适合复杂表单。
RouterModule 路由核心模块,通过 forRoot()(根模块)/forChild()(子模块)配置路由。
HttpClientModule 提供 HTTP 请求能力(替代 AngularJS 的 $http),支持拦截器、TypeScript 类型。

3. 什么是 Angular 组件(Component)?它的核心组成部分有哪些?

组件是 Angular 应用的最小视图单元,负责封装 UI 结构、样式和逻辑,是“页面积木”。一个完整的组件由 4 部分组成:

  1. 装饰器(@Component:定义组件元数据,核心属性包括:

    • selector:组件的 HTML 标签名(如 <app-user>),用于在其他模板中引用。
    • template/templateUrl:组件的 HTML 模板(内联模板/外部文件路径)。
    • styles/styleUrls:组件的 CSS 样式(内联样式/外部文件路径),默认样式隔离(仅作用于当前组件)。
    • providers:在组件层级注入依赖(覆盖模块级注入)。
  2. 类(Class):包含组件的业务逻辑,如数据(property)、方法(method),通过模板绑定与视图交互。

  3. 模板(Template):HTML 结构,通过 Angular 模板语法(如 { {}}[]())绑定类中的数据和事件。

  4. 样式(Styles):组件的样式,支持 scoped(默认)、::ng-deep(穿透子组件样式)等特性。

示例

// user.component.ts
import {
   
    Component } from '@angular/core';

@Component({
   
   
  selector: 'app-user',
  template: `
    <h2>Hello, {
    
    { userName }}!</h2>
    <button (click)="changeName()">Change Name</button>
  `,
  styles: [`h2 { color: blue; }`]
})
export class UserComponent {
   
   
  userName = 'Alice'; // 数据
  changeName() {
   
    // 方法
    this.userName = 'Bob';
  }
}

二、模板语法与数据绑定

1. Angular 有哪些数据绑定方式?分别用于什么场景?

Angular 提供 4 种核心绑定方式,覆盖“数据从类到视图”“视图到类”“双向同步”的场景:

绑定类型 语法示例 方向 作用场景
插值绑定 { { user.name }} 类 → 视图 展示类中的数据(文本内容)。
属性绑定 <img [src]="imgUrl"> 类 → 视图 绑定 HTML 属性/组件输入属性(如 [disabled])。
事件绑定 <button (click)="onClick()"> 视图 → 类 监听 DOM 事件/组件输出事件(如点击、输入)。
双向绑定 <input [(ngModel)]="user.name"> 类 ↔ 视图 数据在类和视图间同步(需导入 FormsModule)。

注意:双向绑定本质是“属性绑定 + 事件绑定”的语法糖,等价于 <input [value]="user.name" (input)="user.name = $event.target.value">

2. 什么是 *ngIf*ngFor?它们的区别和注意事项是什么?

两者都是 Angular 内置结构型指令(前缀 * 表示“修改 DOM 结构”):

*ngIf:条件渲染
  • 作用:根据表达式布尔值决定是否在 DOM 中添加/移除元素(而非隐藏)。
  • 示例<div *ngIf="isShow">仅当 isShow 为 true 时显示</div>
  • 注意:频繁切换可能触发 DOM 频繁创建/销毁,性能敏感场景可考虑 [hidden](仅隐藏,DOM 保留)。
*ngFor:循环渲染
  • 作用:根据数组/可迭代对象生成重复的 DOM 元素。
  • 核心语法*ngFor="let item of list; let i = index; trackBy: trackByFn"
  • 注意事项
    1. 必须加 trackBy:默认情况下,数组变化时 *ngFor 会重新渲染所有元素;trackBy 通过唯一标识(如 id)复用 DOM,提升性能。
    2. index 变量:获取当前循环的索引(从 0 开始)。

trackBy 示例

// 组件类
trackByUserId(index: number, user: User): number {
   
   
  return user.id; // 用用户唯一 ID 跟踪
}

// 模板
<div *ngFor="let user of userList; trackBy: trackByUserId">
  {
   
   {
   
    user.name }}
</div>

3. 什么是管道(Pipe)?常用的内置管道有哪些?

管道是 Angular 中用于转换模板数据格式的工具(如日期、货币、大小写转换),语法为 { { 数据 | 管道名: 参数 }}

常用内置管道:
  • date:格式化日期,示例:{ { today | date: 'yyyy-MM-dd HH:mm' }}(输出:2024-05-20 14:30)。
  • currency:格式化货币,示例:{ { price | currency: 'CNY' }}(输出:¥100.00)。
  • uppercase/lowercase:转换大小写,示例:{ { 'hello' | uppercase }}(输出:HELLO)。
  • async:处理异步数据(如 ObservablePromise),自动订阅/取消订阅,避免内存泄漏,示例:{ { user$ | async }}
  • json:将对象转为 JSON 字符串,用于调试,示例:{ { user | json }}
自定义管道:

通过 @Pipe 装饰器定义,需实现 PipeTransform 接口的 transform 方法。示例(首字母大写管道):

import {
   
    Pipe, PipeTransform } from '@angular/core';

@Pipe({
   
    name: 'firstUpper' }) // 管道名称
export class FirstUpperPipe implements PipeTransform {
   
   
  transform(value: string): string {
   
   
    if (!value) return '';
    return value[0].toUpperCase() + value.slice(1);
  }
}

// 模板使用:{
   
   { 'angular' | firstUpper }} → 输出 Angular

三、组件通信

1. 父组件如何向子组件传递数据?

通过输入属性(@Input() 实现,步骤如下:

  1. 子组件中用 @Input() 装饰器定义可接收的属性:

    // 子组件:child.component.ts
    import {
         
          Input } from '@angular/core';
    
    export class ChildComponent {
         
         
      @Input() childName: string; // 父组件可传递的属性
      @Input('alias') age: number; // 可选:设置别名,父组件用别名传递
    }
    
  2. 父组件模板中通过属性绑定传递数据:

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Liquad Li 李庆军

您的鼓励是我创作的动力哦

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值