面试题答案
一键面试使用@Input()
装饰器的最佳实践
- 减少不必要的更新:仅在输入值真正发生变化时触发组件更新。例如,在子组件中,可以通过比较新旧输入值来决定是否进行进一步操作。
import { Component, Input, SimpleChanges, OnChanges } from '@angular/core';
@Component({
selector: 'app-child',
templateUrl: './child.component.html'
})
export class ChildComponent implements OnChanges {
@Input() data: any;
previousData: any;
ngOnChanges(changes: SimpleChanges) {
if (changes.data && changes.data.currentValue!== this.previousData) {
this.previousData = changes.data.currentValue;
// 在此处执行数据变化后的操作
}
}
}
- 设置合适的访问级别:根据组件的设计,合理设置
@Input()
属性的访问级别为public
、protected
或private
。一般情况下,如果属性仅在组件内部使用,可设置为private
。
不可变数据的运用
- 原理:不可变数据指一旦创建,其状态就不能被改变的数据。在组件间传递不可变数据,可以让Angular更高效地检测数据变化。
- 示例:使用
immer
库来处理不可变数据。假设顶层组件有一个数组数据要传递给深层子组件。
import { Component } from '@angular/core';
import produce from 'immer';
@Component({
selector: 'app-parent',
templateUrl: './parent.component.html'
})
export class ParentComponent {
dataArray = [1, 2, 3];
updateData() {
this.dataArray = produce(this.dataArray, draft => {
draft.push(4);
});
}
}
通过immer
库创建新的数组,确保数据不可变,这样Angular可以更准确地检测到数据变化,避免不必要的组件更新。
OnPush
变更检测策略
- 原理:当组件使用
OnPush
策略时,Angular只会在以下几种情况检查该组件及其子组件:- 输入属性值变化
- 接收到事件
- 手动调用
ChangeDetectorRef.markForCheck()
- 示例:在子组件中启用
OnPush
策略。
import { Component, Input, ChangeDetectionStrategy } from '@angular/core';
@Component({
selector: 'app-child',
templateUrl: './child.component.html',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ChildComponent {
@Input() data: any;
}
结合前面的不可变数据,当传递不可变数据时,由于数据本身不变,Angular不会触发OnPush
组件的变更检测,从而提升性能。例如,顶层组件传递不可变数组给OnPush
策略的子组件,只要数组引用不变,子组件不会重新检测。
协同工作提升性能
- 综合示例:顶层组件将不可变数据传递给启用
OnPush
策略的深层子组件,并且子组件通过@Input()
装饰器优化对输入数据的处理。- 顶层组件(
ParentComponent
)
- 顶层组件(
import { Component } from '@angular/core';
import produce from 'immer';
@Component({
selector: 'app-parent',
templateUrl: './parent.component.html'
})
export class ParentComponent {
user = { name: 'John', age: 30 };
updateUser() {
this.user = produce(this.user, draft => {
draft.age++;
});
}
}
- 深层子组件(
ChildComponent
,启用OnPush
策略)
import { Component, Input, ChangeDetectionStrategy } from '@angular/core';
@Component({
selector: 'app-child',
templateUrl: './child.component.html',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ChildComponent {
@Input() user: any;
}
通过这种方式,只有当user
对象的引用发生变化(即通过immer
产生新的不可变对象)时,ChildComponent
才会触发变更检测,并且子组件通过@Input()
优化对输入数据的处理,有效提升多层嵌套组件结构的性能。