Risposte:
A partire da AngularJS 1.3 c'è un nuovo metodo chiamato $watchGroup
per osservare una serie di espressioni.
$scope.foo = 'foo';
$scope.bar = 'bar';
$scope.$watchGroup(['foo', 'bar'], function(newValues, oldValues, scope) {
// newValues array contains the current values of the watch expressions
// with the indexes matching those of the watchExpression array
// i.e.
// newValues[0] -> $scope.foo
// and
// newValues[1] -> $scope.bar
});
$scope.$watchGroup(['mycustomctrl.foo', 'mycustomctrl.bar'],...
newValues
e oldValues
come undefined
, mentre individualmente le proprietà funzionano come al solito.
A partire da AngularJS 1.1.4 è possibile utilizzare $watchCollection
:
$scope.$watchCollection('[item1, item2]', function(newValues, oldValues){
// do stuff here
// newValues and oldValues contain the new and respectively old value
// of the observed collection array
});
Esempio di Plunker qui
Documentazione qui
$watchCollection
è destinato a consegnare un oggetto e fornire un orologio per le modifiche a qualsiasi proprietà dell'oggetto, mentre $watchGroup
è destinato a essere consegnato una serie di singole proprietà a cui prestare attenzione per le modifiche. Leggermente diverso per affrontare problemi simili ma diversi. Accidenti!
$watch
il primo parametro può anche essere una funzione.
$scope.$watch(function watchBothItems() {
return itemsCombinedValue();
}, function whenItemsChange() {
//stuff
});
Se i due valori combinati sono semplici, il primo parametro è normalmente solo un'espressione angolare. Ad esempio, firstName e lastName:
$scope.$watch('firstName + lastName', function() {
//stuff
});
fullName = firstName + " " + lastName
richiede il passaggio di una funzione come primo argomento (anziché una semplice espressione come 'firstName, lastName'
). Angular è così potente, ma ci sono alcune aree in cui può essere enormemente più favorevole agli sviluppatori in modi che non sembrano compromettere le prestazioni o i principi di progettazione.
$scope.$watch('firstName + lastName', function() {...})
. Si potrebbe anche solo fare due orologi: function nameChanged() {}; $scope.$watch('firstName', nameChanged); $scope.$watch('lastName', nameChanged);
. Ho aggiunto il semplice caso alla risposta.
Ecco una soluzione molto simile al tuo pseudo-codice originale che funziona davvero:
$scope.$watch('[item1, item2] | json', function () { });
EDIT: Okay, penso che sia ancora meglio:
$scope.$watch('[item1, item2]', function () { }, true);
Fondamentalmente stiamo saltando il passo json, che all'inizio sembrava stupido, ma non funzionava senza di essa. La chiave è il terzo parametro spesso omesso che attiva l'uguaglianza degli oggetti rispetto all'uguaglianza di riferimento. Quindi i confronti tra i nostri oggetti array creati in realtà funzionano correttamente.
TypeError: Object #<Object> has no method '$watchCollection'
ma questa soluzione mi aiuta a risolvere il mio problema!
$scope.$watch('[chaptercontent.Id, anchorid]', function (newValues, oldValues) { ... }, true);
È possibile utilizzare le funzioni in $ watchGroup per selezionare i campi di un oggetto nell'ambito.
$scope.$watchGroup(
[function () { return _this.$scope.ViewModel.Monitor1Scale; },
function () { return _this.$scope.ViewModel.Monitor2Scale; }],
function (newVal, oldVal, scope)
{
if (newVal != oldVal) {
_this.updateMonitorScales();
}
});
_this
? L'ambito non viene trasferito nelle funzioni senza definirlo esplicitamente?
Perché non semplicemente avvolgerlo in un forEach
?
angular.forEach(['a', 'b', 'c'], function (key) {
scope.$watch(key, function (v) {
changed();
});
});
Si tratta dello stesso overhead di fornire una funzione per il valore combinato, senza doversi preoccupare della composizione del valore .
changed()
viene invocato ogni volta che qualcosa cambia in una delle proprietà. Questo è esattamente lo stesso comportamento di una funzione per il valore combinato.
Una soluzione leggermente più sicura per combinare i valori potrebbe essere quella di utilizzare quanto segue come $watch
funzione:
function() { return angular.toJson([item1, item2]) }
o
$scope.$watch(
function() {
return angular.toJson([item1, item2]);
},
function() {
// Stuff to do after either value changes
});
$ watch primo parametro può essere espressione o funzione angolare . Vedi la documentazione su $ scope. $ Watch . Contiene molte informazioni utili su come funziona il metodo $ watch: quando viene chiamato watchExpression, come angolare confronta i risultati, ecc.
che ne dite di:
scope.$watch(function() {
return {
a: thing-one,
b: thing-two,
c: red-fish,
d: blue-fish
};
}, listener...);
true
parametro da scope.$watch
(come nel tuo esempio), listener()
verrebbe attivato ogni volta, perché l'hash anonimo ha un riferimento diverso ogni volta.
return { a: functionA(), b: functionB(), ... }
. Quindi controllo gli oggetti restituiti dei valori vecchi e nuovi uno contro l'altro.
$scope.$watch('age + name', function () {
//called when name or age changed
});
Qui la funzione verrà chiamata quando vengono cambiati sia il valore di età che il nome.
Angular introdotto $watchGroup
nella versione 1.3 con cui possiamo guardare più variabili, con un singolo $watchGroup
blocco
$watchGroup
prende l'array come primo parametro in cui possiamo includere tutte le nostre variabili da guardare.
$scope.$watchGroup(['var1','var2'],function(newVals,oldVals){
console.log("new value of var1 = " newVals[0]);
console.log("new value of var2 = " newVals[1]);
console.log("old value of var1 = " oldVals[0]);
console.log("old value of var2 = " oldVals[1]);
});