ngDoCheck VS 使用函数作为属性值 - 性能差异

Posted

技术标签:

【中文标题】ngDoCheck VS 使用函数作为属性值 - 性能差异【英文标题】:ngDoCheck VS using function as attribute value - Performace difference 【发布时间】:2020-03-22 08:09:08 【问题描述】:

我在网页中有一个锚标记,其 href 值取决于属性不受此组件控制的服务。服务详细信息是异步填充的。

为了获取服务详细信息并创建 href 值,我想到了两种方法。 我的问题是 - 在性能方面哪个更好?什么应该是更好的选择?

使用函数作为 href 属性

这会导致函数被连续调用。

// Inside component.html
<div>
    <a [href]="getDetailsLink()"></a>
</div>

// Inside component.ts
@Component( selector: 'user', template: `...` )
class UserComponent implements DoCheck 

    public detailsLink: string;

    constructor(
        private userService: UserService
    ) 

    

    public getDetailsLink(): string 
        // Based on the below property
        const checkSomeProperty = this.userService.checkSomeProperty;

        // Construct details link
        this.detailsLink = `https://www.something.com/users/$this.userService.checkSomeProperty.someValue`;
    

使用 ngDoCheck

// Inside component.html
<div>
    <a [href]="detailsLink"></a>
</div>

// Inside component.ts
@Component( selector: 'user', template: `...` )
class UserComponent implements DoCheck 

    public detailsLink: string;

    constructor(
        private userService: UserService
    ) 

    

    ngDoCheck() 
        if (this.userService.checkSomeProperty) 

            // Check changes for the property
            // Perform required action
            // Construct details link
            this.detailsLink = `https://www.something.com/users/$this.userService.checkSomeProperty.someValue`;
        
    

感谢您阅读到这里。任何指导表示赞赏

【问题讨论】:

两者都不是。使用可观察的。这就是他们的目的。 【参考方案1】:

您有一些业务逻辑来生成该 url,而服务是业务逻辑的地方。解决方案一是这里的方法。

话虽如此,基于链接的https://www.something.com/users/ 部分是否为静态的事实,我也会考虑使用管道来构建这样的网址,以利用记忆。

你最终会得到类似的东西:

<a [href]="someUser | buildLink"></a>

【讨论】:

如果我使用管道,我想我仍然会遇到 this.userService.checkSomeProperty 中数据不可用的问题? 此外,对于简单的手动检查,管道看起来可能比 ngDoCheck 具有额外的性能开销indepth.dev/…【参考方案2】:

我认为第一种方法应该绝对避免

如果以这种方式使用函数,它将在每个可能影响性能的更改检测周期中被调用(有时,以可见的方式)。

ngDoCheck 还将在每个更改检测周期中调用,因此我会避免在此处添加任何严肃的工作。

Massimiliano 提出了一种方法:使用管道,这样您就可以利用记忆的力量。 Here is a great talk 增强了使用管道的好处。

然而,我认为对于这种情况,管道是不需要的。

如果你说这个值依赖于一个服务异步提供的值,你可以把这个逻辑包装成SubjectsObservers

user.service.ts

export class UserService 
    private linkChangedSubj = new Subject();

    get linkChanged$ () 
        return this.linkChangedSubj.asObservable();
    


    changeLink (newLink) 
        /* ... */

        this.linkChangedSubj.next(newLink);
    

user.component.ts

export class UserComponent 

    constructor (private userService: UserService)  

    ngOnInit () 
        this.userService.linkChanged$
            .pipe(takeUntil(this.unsubscribe$))
            .subscribe(newLink => this.detailsLink = newLink)
    

【讨论】:

这是解决这个问题的方法,甚至可以通过使用异步管道而不是使用unsubscribe 信号方法来改进。在每个更改检测周期检查某些服务属性将永远不会执行良好。这就是主题的用途。

以上是关于ngDoCheck VS 使用函数作为属性值 - 性能差异的主要内容,如果未能解决你的问题,请参考以下文章

Angular-ngDoCheck

无法从 VS2019 中的 Boost 属性树映射值中获取值()

在 SwiftUI 中使用泛型作为函数属性的默认值

使用 EventSubscriber 将函数的返回值作为属性传递给 json

VS代码查找xml属性并替换为当前值*因子

VS2010 如何在程序中更改Button控件的Disable属性值 C++