javascript - interval - settimeout jquery ejemplo
Vista refrescante Angular2 en empuje de matriz (2)
Parece que no puedo obtener la vista angular2 para actualizar en una función array.push, invocada desde una operación asincrónica setInterval.
el código es de este ejemplo de plunkr angular de setInterval :
Lo que intento hacer es lo siguiente:
import {View, Component, bootstrap, Directive, ChangeDetectionStrategy, ChangeDetectorRef} from ''angular2/angular2''
@Component({selector: ''cmp'', changeDetection: ChangeDetectionStrategy.OnPush})
@View({template: `Number of ticks: {{numberOfTicks}}`})
class Cmp {
numberOfTicks = [];
constructor(private ref: ChangeDetectorRef) {
setInterval(() => {
this.numberOfTicks.push(3);
this.ref.markForCheck();
}, 1000);
}
}
@Component({
selector: ''app'',
changeDetection: ChangeDetectionStrategy.OnPush
})
@View({
template: `
<cmp><cmp>
`,
directives: [Cmp]
})
class App {
}
bootstrap(App);
<!DOCTYPE html>
<html>
<head>
<title>angular2 playground</title>
<script src="https://code.angularjs.org/tools/traceur-runtime.js"></script>
<script src="https://code.angularjs.org/tools/system.js"></script>
<script src="https://code.angularjs.org/tools/typescript.js"></script>
<script data-require="jasmine" data-semver="2.2.1" src="http://cdnjs.cloudflare.com/ajax/libs/jasmine/2.2.1/jasmine.js"></script>
<script data-require="jasmine" data-semver="2.2.1" src="http://cdnjs.cloudflare.com/ajax/libs/jasmine/2.2.1/jasmine-html.js"></script>
<script data-require="jasmine@*" data-semver="2.2.1" src="http://cdnjs.cloudflare.com/ajax/libs/jasmine/2.2.1/boot.js"></script>
<script src="config.js"></script>
<script src="https://code.angularjs.org/2.0.0-alpha.37/angular2.min.js"></script>
<script>
System.import(''app'')
.catch(console.error.bind(console));
</script>
</head>
<body>
<app></app>
</body>
</html>
El código anterior funcionará correctamente si "numberOfTicks" es solo un número, (como muestra el ejemplo original de plunker) pero una vez que lo cambio a una matriz y datos de inserción, no se actualizará.
No puedo entender por qué es eso.
El siguiente comportamiento es similar a un problema que tengo cuando intento actualizar un gráfico en angular2 con nuevos puntos de datos cuando uso setInterval / setTimeout.
Gracias por la ayuda.
Debe actualizar toda la referencia de su matriz después de agregar un elemento en ella:
constructor(private ref: ChangeDetectorRef) {
setInterval(() => {
this.numberOfTicks.push(3);
this.numberOfTicks = this.numberOfTicks.slice();
this.ref.markForCheck();
}, 1000);
}
}
Editar
La interfaz DoCheck también podría interesarle, ya que le permite conectar su propio algoritmo de detección de cambios.
Vea este enlace para más detalles:
Aquí hay una muestra:
@Component({
selector: ''custom-check'',
template: `
<ul>
<li *ngFor="#line of logs">{{line}}</li>
</ul>`
})
class CustomCheckComponent implements DoCheck {
@Input() list: any[];
differ: any;
logs = [];
constructor(differs: IterableDiffers) {
this.differ = differs.find([]).create(null);
}
ngDoCheck() {
var changes = this.differ.diff(this.list);
if (changes) {
changes.forEachAddedItem(r => this.logs.push(''added '' + r.item));
changes.forEachRemovedItem(r => this.logs.push(''removed '' + r.item))
}
}
}
El código anterior funcionará correctamente si "numberOfTicks" es solo un número, pero una vez que lo cambie a una matriz y presione datos, no se actualizará. No puedo entender por qué es eso.
Se debe a que un número es un tipo primitivo de JavaScript y una matriz es un tipo de referencia de JavaScript. Cuando se ejecuta la detección de cambio angular, utiliza ===
para determinar si un enlace de plantilla ha cambiado.
Si {{numberOfTicks}}
es un tipo primitivo, ===
compara los valores actuales y anteriores. Entonces los valores 0
y 1
son diferentes.
Si {{numberOfTicks}}
es un tipo de referencia, ===
compara los valores actuales y anteriores (de referencia). Entonces, si la referencia de matriz no cambia, Angular no detectará un cambio. En su caso, al usar push()
, la referencia de matriz no cambia.
Si pone lo siguiente en su plantilla en su lugar
<div *ngFor="#tick of numberOfTicks">{{tick}}</div>
entonces Angular actualizaría la vista porque hay un enlace para cada elemento de la matriz, en lugar de solo la matriz misma. Por lo tanto, si un elemento nuevo es push()
ed, o un elemento existente se elimina o cambia, se detectarán todos estos cambios.
Por lo tanto, en su chart plunker, lo siguiente debe actualizarse cuando cambien los contenidos de las matrices from
y to
:
<span *ngFor="#item of from">{{item}}</span>
<span *ngFor="#item of to">{{item}}</span>
Bueno, se actualizará si cada elemento es un tipo primitivo.