在TypeScript和Angular中使用Getter和Setter
getter 和 setter 是一种众所周知的模式,在不同的语言中使用。在本文中,我想通过 TypeScript 中的示例帮助您理解 getter 和 setter。看看它如何在 Angular 应用程序中发挥作用。
首先简单介绍一下 TypeScript。
1. TypeScript 中的 Getter 和 Setter
假设我们有一个简单的产品类,其属性为:价格、名称、序列号。
1 | export class Product { |
这里我们有一个私有属性 price 和两个公共属性 name 和 serialNumber(序列号)。我们决定创建一个新的产品类实例——汽车。正如您在下图中看到的,我们可以访问 Product 类的任何公共属性,但不能访问私有属性。Price 属性只能从 Product 类访问,而不能从外部访问。
1 | export class Product { |
为了解决这个问题,我们可以使用 getter 和 setter。Getter 和 Setter 是几乎所有语言中常用的模式。它们可以帮助您向属性添加额外的逻辑,正如我们将在上面看到的那样。
因此,让我们将价格属性设为私有,并为其添加 getter 和 setter。
1 | export class Product { |
语法很简单,对吧?现在我们调用的不是私有属性,而是同名的 setter。并且我们可以通过 getter 获取私有属性的值。通过以上修改,我们可以汽车实例中访问价格属性了。
除此之外,现在我们可以向 set 方法添加额外的逻辑。例如,在给价格赋值之前, 检查检查价格是否合理以及许多更复杂的逻辑。
1 | export class Product { |
2. Angular 中的 Getter 和 Setter
在 Angular 中,getter 和 setter 经常被用作拦截输入属性更改的方法之一。例如,我们有两个组件。products 作为父组件,product 作为子组件,具有两个输入(价格、名称)。
1 | <app-product name="Soda" price="100"> </app-product> |
1 | export class ProductComponent { |
因此,每当我们有一个输入值时,setter 就会被触发,正如我们上面所做的那样,我们可以向我们的 setter 添加一些额外的逻辑。但是在 setter 使用额外逻辑有一些限制:
不要在 setter 中使用 side effects。
不要在 setter 中使用订阅。
不要使用_elementRef.detectChanges()。如果确实有必要,例如您在 setter 中调用一个方法来切换 ngStyle 属性中使用的某些属性或使用类似的 css 变量,那么最好选择_elementRef.markForCheck()。Angular 不接受输入属性 detectChanges,可能会导致控制台错误和性能问题
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34(
{
selector: 'app-product-component',
changeDetection: ChangeDetectionStrategy.OnPush
}
)
export class ProductComponent {
private _borderSize: number;
constructor(private _elementRef: ElementRef) {
}
()
public get borderSize(): number {
return this._borderSize;
}
public set borderSize(value: number) {
this._borderSize = value;
this.setStyles(value)
}
private setStyles(borderSize: number) {
this._elementRef.nativeElement.style.setProperty(
'--offset',
'${borderSize + 'px'}'
)
this._elementRef.markForCheck();
}
}如果您将 non-primitive 对象向下传递给子组件时,并在子组件中更改该对象的某个属性,则通常也会出现变更不生效的情况。因为父组件保持的对该对象的引用而不是值本身, 虽然对象的属性改变了, 引用并没有变, 所有父组件侦察不到变化。如果您使用 OnPush 更改检测策略来配置组件,您可能会发现由于底层对象引用没有修改,因此不会触发值变更检测。您经常会遇到这种情况, 尤其使用硬编码时,这些值不是来自异步流(例如 Observable)。
如果您使用 Angular 的默认更改检测机制,则允许直接对象变更,因此将检测到在不提供新引用的情况下对对象进行的更改。
但是,如果您不应用默认的更改检测 - 只需使用 Observable 和异步管道就是您的方式!
3. Angular 系列文章
最新更新以及更多 Angular 相关文章请访问 Angular 合集 | 鹏叔的技术博客
4. 总结
在这里,我尝试描述 TypeScript 中 getter 和 setter 的常见原理,以及在 Angular 应用程序中使用它们的一些有用技巧。希望这篇文章对您有所帮助,
5. 参考文档
在TypeScript和Angular中使用Getter和Setter