面试题答案
一键面试-
创建管道:
- 首先,在Angular项目中使用命令行工具创建一个管道,例如
ng generate pipe studentGrade
。这将生成一个管道类,如下所示:
import { Pipe, PipeTransform } from '@angular/core'; @Pipe({ name:'studentGrade' }) export class StudentGradePipe implements PipeTransform { transform(value: any[],...args: unknown[]): any { // 这里开始处理数据转换 let result = []; value.forEach(student => { student.grades.forEach(grade => { result.push({ name: student.name, course: grade.course, score: grade.score }); }); }); return result; } }
- 上述管道的作用是将输入的复杂嵌套对象数组,转换为一个更扁平的数组,每个元素包含学生名字、课程名和成绩。这样的结构更适合在视图中展示。
- 首先,在Angular项目中使用命令行工具创建一个管道,例如
-
在模块中声明管道:
- 在相关的模块(如
app.module.ts
)中,将创建的管道声明到declarations
数组中:
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform - browser'; import { AppComponent } from './app.component'; import { StudentGradePipe } from './student - grade.pipe'; @NgModule({ declarations: [ AppComponent, StudentGradePipe ], imports: [ BrowserModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule {}
- 在相关的模块(如
-
在视图中使用管道:
- 假设在组件的模板文件(如
app.component.html
)中有如下代码:
<ul> <li *ngFor="let item of students | studentGrade"> {{item.name}} - {{item.course}}: {{item.score}} </li> </ul>
- 这里
students
是组件类中包含复杂嵌套对象数组的数据属性。通过管道studentGrade
的转换,在视图中遍历展示每个学生的名字及其每门课程的成绩。
- 假设在组件的模板文件(如
-
优化性能避免不必要的重新渲染:
- 为了避免不必要的重新渲染,可以使用
pure
管道。Angular中的管道默认是pure
的,这意味着只有当输入值是原始类型(如字符串、数字等)发生变化,或者引用类型(如对象、数组)的引用发生变化时,管道才会重新执行。 - 在我们的场景中,如果
students
数组的引用没有发生变化,即使数组内部的数据改变了,管道也不会重新执行。如果需要在数组内部数据变化时也执行管道,可以将管道设置为impure
。但这样会增加性能开销,因为Angular会更频繁地检查管道是否需要重新执行。 - 如果要保持
pure
管道且希望在数组内部数据变化时进行更新,可以使用ChangeDetectorRef
。例如,在组件类中注入ChangeDetectorRef
,并在数据变化时手动调用detectChanges
方法。但在大多数情况下,通过合理设计数据结构,保持pure
管道的默认行为可以在一定程度上优化性能,避免不必要的重新渲染。
import { Component, ChangeDetectorRef } from '@angular/core'; @Component({ selector: 'app - component', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { students = [ { 'name': 'John', 'grades': [ { 'course': 'Math','score': 85 }, { 'course': 'Science','score': 90 } ] }, { 'name': 'Jane', 'grades': [ { 'course': 'Math','score': 92 }, { 'course': 'Science','score': 88 } ] } ]; constructor(private cdr: ChangeDetectorRef) {} updateStudentGrade() { // 假设这里更新了学生成绩 this.students[0].grades[0].score = 90; this.cdr.detectChanges(); } }
- 但通常情况下,尽量避免直接修改数据结构,而是通过创建新的数据结构来触发
pure
管道的重新执行,这样可以更好地利用Angular的变化检测机制优化性能。例如:
updateStudentGrade() { let newStudents = [...this.students]; newStudents[0].grades[0].score = 90; this.students = newStudents; }
- 这样,
students
数组的引用发生了变化,pure
管道会重新执行,从而更新视图,同时也避免了不必要的频繁重新渲染。
- 为了避免不必要的重新渲染,可以使用