wake-up-neo.com

$ ein Objekt beobachten

Ich möchte auf Änderungen in einem Wörterbuch achten, aber aus irgendeinem Grund wird Watch Callback nicht aufgerufen.

Hier ist ein Controller, den ich benutze:

function MyController($scope) {
    $scope.form = {
        name: 'my name',
        surname: 'surname'
    }

    $scope.$watch('form', function(newVal, oldVal){
        console.log('changed');
    });
}

Hier ist Geige .

Ich gehe davon aus, dass $ watch-Rückruf bei jeder Änderung des Namens oder Nachnamens ausgelöst wird. Dies geschieht jedoch nicht.

Was ist der richtige Weg, dies zu tun?

307

Rufen Sie $watch mit true als drittem Argument auf:

$scope.$watch('form', function(newVal, oldVal){
    console.log('changed');
}, true);

Beim Vergleich zweier komplexer Objekte in JavaScript werden diese standardmäßig auf "Verweis" - Gleichheit geprüft. Dabei werden Sie gefragt, ob sich die beiden Objekte auf dasselbe beziehen, und nicht auf "Wert". Dabei werden die Werte aller Eigenschaften dieser Objekte geprüft Objekte sind gleich.

Gemäß der Angular-Dokumentation ist der dritte Parameter für objectEquality:

Bei objectEquality == true wird die Ungleichung von watchExpression gemäß der Funktion angular.equals bestimmt. Um den Wert des Objekts zum späteren Vergleich zu speichern, wird die Funktion angular.copy verwendet. Das bedeutet daher, dass das Beobachten komplexer Objekte nachteilige Auswirkungen auf das Gedächtnis und die Leistung hat.

551
rossipedia

Das form-Objekt ändert sich nicht, nur die name-Eigenschaft ist

aktualisiert Geige

function MyController($scope) {
$scope.form = {
    name: 'my name',
}

$scope.changeCount = 0;
$scope.$watch('form.name', function(newVal, oldVal){
    console.log('changed');
    $scope.changeCount++;
});
}
13
Jason

Kleiner Leistungstipp wenn jemand einen Datastore-Dienst mit Schlüssel -> Wertepaaren hat:

Wenn Sie einen Dienst namens dataStore haben, können Sie einen Zeitstempel aktualisieren, wenn sich Ihr Big Data-Objekt ändert. Auf diese Weise beobachten Sie nicht das gesamte Objekt, sondern beobachten nur einen Zeitstempel für die Änderung.

app.factory('dataStore', function () {

    var store = { data: [], change: [] };

    // when storing the data, updating the timestamp
    store.setData = function(key, data){
        store.data[key] = data;
        store.setChange(key);
    }

    // get the change to watch
    store.getChange = function(key){
        return store.change[key];
    }

    // set the change
    store.setChange = function(key){
        store.change[key] = new Date().getTime();
    }

});

Und in einer Direktive beobachten Sie nur den Zeitstempel, der geändert werden soll

app.directive("myDir", function ($scope, dataStore) {
    $scope.dataStore = dataStore;
    $scope.$watch('dataStore.getChange("myKey")', function(newVal, oldVal){
        if(newVal !== oldVal && newVal){
            // Data changed
        }
    });
});
12
Ferenc Takacs

Der Grund dafür, dass Ihr Code nicht funktioniert, liegt darin, dass $watch standardmäßig auf die Überprüfung überprüft. Kurz gesagt, stellen Sie sicher, dass das Objekt, das an es übergeben wird, ein neues Objekt ist. In Ihrem Fall ändern Sie jedoch nur eine Eigenschaft eines Formularobjekts, ohne ein neues zu erstellen. Damit dies funktioniert, können Sie als dritten Parameter true übergeben.

$scope.$watch('form', function(newVal, oldVal){
    console.log('invoked');
}, true);

Es wird funktionieren, aber Sie können $ watchCollection verwenden, was effizienter ist als $ watch, da $watchCollection auf flache Eigenschaften des Formularobjekts achtet. Z.B.

$scope.$watchCollection('form', function (newVal, oldVal) {
    console.log(newVal, oldVal);
});
4
sol4me

Wenn Sie nach Änderungen an Formularobjekten suchen, verwenden Sie am besten den Beobachtungsansatz
$watchCollection. Bitte beachten Sie die offiziellen Dokumentationen für verschiedene Leistungsmerkmale.

4

Versuche dies:

function MyController($scope) {
    $scope.form = {
        name: 'my name',
        surname: 'surname'
    }

    function track(newValue, oldValue, scope) {
        console.log('changed');
    };

    $scope.$watch('form.name', track);
}
1
Tarun

Für jeden, der auf eine Änderung an einem Objekt innerhalb eines Arrays von Objekten achten möchte, schien dies für mich zu funktionieren (wie bei den anderen Lösungen auf dieser Seite nicht):

function MyController($scope) {

    $scope.array = [
        data1: {
            name: 'name',
            surname: 'surname'
        },
        data2: {
            name: 'name',
            surname: 'surname'
        },
    ]


    $scope.$watch(function() {
        return $scope.data,
    function(newVal, oldVal){
        console.log(newVal, oldVal);
    }, true);
0
Max