Does angular trigger change detection when setting a variable to the same value

Viewed 695

I was wondering if, doing so

<nav [class.haveScrolled]="haveScrolled"></nav>
haveScrolled = false

@HostListener('window:scroll', ['$event'])
checkOffsetTop() {
  this.haveScrolled = window.pageYOffset !== 0
}

Will force a rerendering of the element even if I do set the same value to the haveScrolled variable over and over again

2 Answers

Ultimately, the answer would be: it depends on the browser's rendering engine optimizations. For example, using Chrome (Version 97.0.4692.71), the element is repainted only when the haveScrolled class has been added to or removed from the DOM. Here is a showcase using Chrome's Rendering tools. Whatever flashes in green represents the occurrence of a new paint event:

enter image description here

I performed the test on this StackBlitz example.

This particular use-case demonstrates what browsers that use the Blink rendering engine would do. I would guess that, for example, Firefox might handle the painting cases differently.

Keep in mind that the StackBlitz example I have provided has a very simple component structure and in no way reflects how an actual real-world app would behave. Usually, the more complex the component structure/interaction is, the more painting events would occur. I encourage you to use your browser's dev tools to monitor the overall performance of the app.

Short answer is YES, even if it's not in a HostListener.

try to play with this and you will see what happens ;)

private _haveScrolled = false;
set haveScrolled(haveScrolled: boolean) {
  console.log('set hasScrolled');
  this._haveScrolled = haveScrolled;
}
get haveScrolled(): boolean {
  console.log('get hasScrolled');
  return this._haveScrolled;
}

in ngOnInit:

setInterval(() => {
  this.haveScrolled = false;
}, 1000);

and

// see https://angular.io/guide/lifecycle-hooks#lifecycle-event-sequence
ngDoCheck() {
  console.log('do check ')
}

you will alway see "do check" even without a getter/setter

Related