倒计时组件:如何防止Angular2中的重新渲染?

时间:2022-08-01 20:10:57

I have an Angular2 master component which includes a number of child components and an independant countdown component (named "clock" in the code below). Countdown component changes it's label every second and that causes the master component and all others to (needlessly) re-render. How can I prevent that? This is the source of my countdown component:

我有一个Angular2主组件,它包含许多子组件和一个独立的倒计时组件(在下面的代码中命名为“clock”)。倒计时组件每秒更改它的标签,这会导致主组件和所有其他组件(不必要地)重新渲染。我怎么能防止这种情况?这是我的倒计时组件的来源:

import {Component, Input} from 'angular2/core';
@Component({
    selector: 'clock',
    template: `
        <span>
            {{caption}}
        </span>
    `
})
export class ClockComponent {
    public caption;
    @Input('seconds') seconds :number = 0;
    constructor() {
      var self = this;
      setInterval(function(){
            self.seconds--;
            self.caption = self.getCaption(self.seconds);
      }, 1000);
      this.caption = this.getCaption(this.seconds);
    }

    getCaption (seconds): string {
        let h = Math.floor(seconds / (60*60));
        let m = Math.floor((seconds - 60 * 60 * h) / 60);
        let s = seconds % 60;
        return ((h < 10) ? '0' : '') + h + ':'
             + ((m < 10) ? '0' : '') + m + ':'
             + ((s < 10) ? '0' : '') + s ;
    }
}

and you can imagine it being embedded alongside others in "my-app"; something like:

你可以想象它和“my-app”中的其他人一起被嵌入;就像是:

<clock [seconds]="1800"></clock>
<other-comps>...</other-comps>...

EDIT (per comment): When I mean re-render, this is what happens: I've added a console.log printout to other components (nav and question, see image below) on various rendering actions, for instance, a component has a class binder, eg: [class.selected]="isSelected" and I've added console.log() to the isSelected() method and can thus spot that it is called every one second, every time the countdown (clock) refreshes itself. I'd like for the countdown to change label (count down from eg 30 minutes) WITHOUT affecting nav and question components and causing them to re-render.

编辑(评论):当我的意思是重新渲染时,会发生这种情况:我已经在各种渲染操作中向其他组件添加了console.log打印输出(导航和问题,请参见下图),例如,组件具有一个类绑定器,例如:[class.selected] =“isSelected”,我已经将console.log()添加到isSelected()方法,因此每次倒计时(时钟)都可以发现它每隔一秒被调用一次刷新自己。我希望倒计时更改标签(从例如30分钟倒计时)而不影响导航和问题组件并导致它们重新渲染。

倒计时组件:如何防止Angular2中的重新渲染?

EDIT (2):

And here is the plunker: http://plnkr.co/edit/PwBfUQXyZyTrqPaqrwRm?p=preview

以下是plunker:http://plnkr.co/edit/PwBfUQXyZyTrqPaqrwRm?p = preview

Fire up the console and watch for six those "q-nav isSelected?" appearing every second (printed from qnav component).

启动控制台并观察六个“q-nav被选中?”每秒出现一次(从qnav组件打印)。

1 个解决方案

#1


3  

That's Angulars change detection that is invoked on every event (setInterval calling the callback is also such an event).

这是在每个事件上调用的Angulars更改检测(调用回调的setInterval也是这样的事件)。

You can witch change detection to OnPush so change detection only takes place when an @Input() is updated or when you invoke change detection explicitely, for example by calling methods on ChangeDetectorRefs

您可以将检测更改为OnPush,因此更改检测仅在更新@Input()或明确调用更改检测时发生,例如通过调用ChangeDetectorRefs上的方法

import {Component, Input, OnInit, EventEmitter, Output, OnChanges, ChangeDetectionStrategy} from 'angular2/core';
@Component({
    selector: 'q-nav',
    template: `
        <span *ngFor="#a of currAnswers; #i = index" class="aii-qn"
            [class.selected]="isSelected(i)"
            (click)="onSelect(i)">
            <span class="badge">{{ i+1 }}</span>
        </span>
    `,
    styles: [`
        .aii-qn {
            color: #0000ff;
            cursor: pointer;
            font-size: 2rem;
        }
        .selected {
            border: black solid 2px;
        }

    `],
    changeDetection: ChangeDetectionStrategy.OnPush
})

for more details see http://blog.thoughtram.io/angular/2016/02/22/angular-2-change-detection-explained.html

有关详细信息,请参阅http://blog.thoughtram.io/angular/2016/02/22/angular-2-change-detection-explained.html

#1


3  

That's Angulars change detection that is invoked on every event (setInterval calling the callback is also such an event).

这是在每个事件上调用的Angulars更改检测(调用回调的setInterval也是这样的事件)。

You can witch change detection to OnPush so change detection only takes place when an @Input() is updated or when you invoke change detection explicitely, for example by calling methods on ChangeDetectorRefs

您可以将检测更改为OnPush,因此更改检测仅在更新@Input()或明确调用更改检测时发生,例如通过调用ChangeDetectorRefs上的方法

import {Component, Input, OnInit, EventEmitter, Output, OnChanges, ChangeDetectionStrategy} from 'angular2/core';
@Component({
    selector: 'q-nav',
    template: `
        <span *ngFor="#a of currAnswers; #i = index" class="aii-qn"
            [class.selected]="isSelected(i)"
            (click)="onSelect(i)">
            <span class="badge">{{ i+1 }}</span>
        </span>
    `,
    styles: [`
        .aii-qn {
            color: #0000ff;
            cursor: pointer;
            font-size: 2rem;
        }
        .selected {
            border: black solid 2px;
        }

    `],
    changeDetection: ChangeDetectionStrategy.OnPush
})

for more details see http://blog.thoughtram.io/angular/2016/02/22/angular-2-change-detection-explained.html

有关详细信息,请参阅http://blog.thoughtram.io/angular/2016/02/22/angular-2-change-detection-explained.html