javascript - orientado - $ ver un objeto
lista de objetos javascript (8)
Debes cambiar en $ watch ....
function MyController($scope) {
$scope.form = {
name: ''my name'',
}
$scope.$watch(''form.name'', function(newVal, oldVal){
console.log(''changed'');
});
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
<div ng-app>
<div ng-controller="MyController">
<label>Name:</label> <input type="text" ng-model="form.name"/>
<pre>
{{ form }}
</pre>
</div>
</div>
Quiero ver los cambios en un diccionario, pero por alguna razón no se llama a la devolución de llamada de vigilancia.
Aquí hay un controlador que uso:
function MyController($scope) {
$scope.form = {
name: ''my name'',
surname: ''surname''
}
$scope.$watch(''form'', function(newVal, oldVal){
console.log(''changed'');
});
}
Aquí está el fiddle .
Espero que se devuelva $ watch callback cada vez que se cambia el nombre o el apellido, pero no sucede.
¿Cuál es la forma correcta de hacerlo?
El objeto de form
no está cambiando, solo la propiedad de name
es
fiddle actualizado
function MyController($scope) {
$scope.form = {
name: ''my name'',
}
$scope.changeCount = 0;
$scope.$watch(''form.name'', function(newVal, oldVal){
console.log(''changed'');
$scope.changeCount++;
});
}
La razón por la que su código no funciona es porque $watch
por defecto hace una verificación de referencia. Entonces, en pocas palabras, asegúrese de que el objeto que se le pasa sea un objeto nuevo. Pero en su caso, solo está modificando alguna propiedad del objeto de formulario que no está creando uno nuevo. Para que funcione, puede pasar true
como tercer parámetro.
$scope.$watch(''form'', function(newVal, oldVal){
console.log(''invoked'');
}, true);
Funcionará pero puede usar $ watchCollection, que será más eficiente que $ watch porque $watchCollection
observará las propiedades superficiales en el objeto de formulario. P.ej
$scope.$watchCollection(''form'', function (newVal, oldVal) {
console.log(newVal, oldVal);
});
Llame a $watch
con true
como el tercer argumento:
$scope.$watch(''form'', function(newVal, oldVal){
console.log(''changed'');
}, true);
Por defecto, al comparar dos objetos complejos en JavaScript, se verificará la igualdad de "referencia", que pregunta si los dos objetos se refieren a la misma cosa, en lugar de la igualdad de "valor", que verifica si los valores de todas las propiedades de esos los objetos son iguales
Según la documentación de Angular , el tercer parámetro es para objectEquality
:
Cuando
objectEquality == true
, la desigualdad de watchExpression se determina de acuerdo con la funciónangular.equals
. Para guardar el valor del objeto para una comparación posterior, seangular.copy
funciónangular.copy
. Por lo tanto, esto significa que observar objetos complejos tendrá implicaciones adversas de memoria y rendimiento.
Mientras busca cambios en los objetos de forma, el mejor enfoque de observación es utilizar
$watchCollection
. Por favor, eche un vistazo a la documentación oficial para diferentes características de rendimiento.
Para cualquiera que quiera ver un cambio en un objeto dentro de un conjunto de objetos, esto parece funcionar para mí (como no lo hicieron las otras soluciones en esta página):
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);
Poco consejo de rendimiento si alguien tiene un tipo de servicio de almacén de datos con pares clave -> valor:
Si tiene un servicio llamado dataStore , puede actualizar una marca de tiempo cada vez que cambie su objeto de big data. De esta manera, en lugar de observar en profundidad todo el objeto, solo está viendo una marca de tiempo para el cambio.
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();
}
});
Y en una directiva solo estás viendo la marca de tiempo para cambiar
app.directive("myDir", function ($scope, dataStore) {
$scope.dataStore = dataStore;
$scope.$watch(''dataStore.getChange("myKey")'', function(newVal, oldVal){
if(newVal !== oldVal && newVal){
// Data changed
}
});
});
Prueba esto:
function MyController($scope) {
$scope.form = {
name: ''my name'',
surname: ''surname''
}
function track(newValue, oldValue, scope) {
console.log(''changed'');
};
$scope.$watch(''form.name'', track);
}