Angular use strict equal ===
operator to tell if bound property value changes, it works well on simple types, such as string, numbers, boolean, but if property value is object
or array
, Angular always think it is not changed as long as the instance not recreate.
Binding without pipe
This behavior not easily observed even we use object
and array
:
<ul>
<li *ngFor="let item of items">{{item.text}}</li>
</ul>
<button (click)="add()">Add</button>
let idx = 0;
export class Foo {
items = [];
add() {
this.items.push({text: `Item: ${idx++}`});
}
}
The above code works even items
is an array
, seems impossible at first glance. It works because: We bind item.text
not items
array object, item.text
is string, not reference type.
If we use Date
type, we can see the odds:
<div>{{v}}</div>
<button (click)="nextDay()">Next Day</button>
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
v = new Date();
nextDay() {
this.v.setDate(this.v.getDate() + 1);
console.log(this.v);
}
}

After click Next Day button, UI not update, through console, we can see the value is changed.

Binding with pipe
For impure pipe, Angular use transformed value to do change detection, for pure pipes, use un-transformed value (the value processed before calling pipe) to do change detection.
Ways to work around:
For normal binding without pipe, it is normally never be a problem, most object binding to HTML DOM are immutable simple values, unless Date
, but Date
is javascript bad design, it should implemented as immutable, and we should always create
a new instance after each change.
For pure pipes:
-
Always re-create reference value on each change, the disadvantage is:
1. interfere application logic, the code may not designed with angular
2. bad performance to create complex object each time, with immutable lib such asreselect
make the code too complex
3. easy to introduce bugs, requires every pieces of code that changes object to obey immutable rules. -
Use
WrappedValue
Document says:
* Indicates that the result of a {@link Pipe} transformation has changed even though the
* reference has not changed.
Wrap the reference object if its content changed.
网友评论