我对Angular/Typescripting有点困惑。我认为应该隐藏属性,以防止对属性值进行任何可能的外部更改。
例如:
export class Foo{
private _bar: string;
constructor(private bar: string){
this._bar = bar;
}
public get bindBar(): string {
return this._bar;
}
}
还有一些模板
<span>{{ bindBar }}</span>
但是在阅读中,由于在页面上发生的每次更改检测下都会调用方法,因此绑定到html模板中的方法存在性能问题。
我看到的选择是要么将其作为公共财产,要么使用管道。
管道似乎有点矫枉过正,必须为需要绑定的页面中的每个属性实现,并且公共变量几乎总是不行的。
我在Angular网站上找不到任何关于如何实现绑定而不会对性能产生负面影响的明确方向,但这种管道式的做法似乎并不正确。
有人可以解释一下吗?
正如您在示例中所看到的,它没有绑定到组件,因为触发的事件会影响其他组件。我的堆栈闪电战 2 组件测试
这个吸气剂
public get bindBar(): string {
return this._bar;
}
不会降低应用程序的性能。调用它所需的时间与直接引用变量所需的时间大致相同。模板中的所有变量也会在每次检测到更改时被引用,以检查它们是否已更改。因此,在模板中调用它与引用公共变量没有什么不同。
也就是说,如果您想使变量为只读,您可以只使用<code>readonly</code>关键字。
readonly bar: string;
不相信我?这里有一个测试:
https://stackblitz.com/edit/angular-ivy-zgjwnw?file=src/app/app.component.ts
超过一百万个变化检测周期,这两种策略用我的硬件大约需要650毫秒。
在更改检测期间调用方法的唯一时间是这些方法是否花费大量时间,或者您正在向 API 发出请求。切勿将这些类型的方法调用放在模板中,除非将它们绑定到事件。
如果您担心性能,您应该更关心实际触发更改检测的次数,以及每次检查多少组件。默认的更改检测策略是检查所有当前组件模板中可能更改某些内容的每个操作的每个变量和方法调用。
OnPush
更改检测策略允许您在检查组件模板时进行更改,而 ChangeDetectorRef.detach()
服务方法允许您完全分离组件,使其不自动检查。
这是一篇很棒的文章,可以了解更多信息:
https://blog.angular-university.io/how-does-angular-2-change-detection-really-work/
我强烈建议在调用ChangeDetectorRef.detect()
并在调试器中遍历更改检测周期之前放置一个断点。您会看到更改检测器将模板中任何插值值的最后一个值(无论它们是属性还是方法调用的结果)保存在一个名为lView
(最后一个视图)的对象中。然后在更改检测周期中,它再次重新计算这些插值值——无论这意味着引用变量还是调用方法。如果任何值不同,那么更改检测器将引用相关的html节点并更改它的值。
在管道的上下文中,变化检测器将检查输入值,并且仅在该值发生变化时调用管道。那是因为管道被假定为纯函数(输出只依赖于输入)。所以如果你在调用一个耗时的纯方法,让它成为管道会更有效率。示例:格式化字符串、执行验证、数学等式、深度比较等。
在打字稿中,使用公共变量并直接访问它们大多是安全的。绑定时,使用方法时事情往往会发生偏差,因此建议在绑定中使用变量。