Как просмотреть все изменения в области в AngularJS? - программирование
Подтвердить что ты не робот

Как просмотреть все изменения в области в AngularJS?

Angular $Функция часов позволяет запускать события при изменении указанного атрибута, как показано ниже. Есть ли аналогичный способ прослушивания событий, когда какие-либо изменения происходят в области?

// works
$scope.$watch("someval", function() { }, true);
$scope.$watch(function(scope){ return scope.someval; }, function() { }, true);

// doesn't work
$scope.$watch("this", function() { }, true);
$scope.$watch(function(scope){ return scope; }, function() { }, true);
4b9b3361

Ответ 1

Я считаю, что вы не можете следить за изменениями на $scope (кроме использования @ValentynShybanov sugestion). Самое близкое, что вы можете сделать, это следить за вызовами дайджеста:

$scope.$watch(function() { 
    console.log("digest called"); 
});

Вышеуказанная функция будет вызываться каждый раз, когда в области видится $digest, , даже если в свойствах области не было изменений.

Ответ 2

Это не просто, потому что область видимости - простой объект. Это Backbone, где вы можете подписаться на все события, но для этого ваши модели должны расширять собственный интерфейс - Backbone.Model. Angular ставит в сторону шаблон наблюдателя в нем классический вид. Это необычное дизайнерское решение. В основном существует цикл, в котором Angular оценивает наблюдаемые выражения и когда обнаруживает отличие от предыдущей итерации, он уведомляет наблюдателей. Действительно интересный подход, вероятно, единственная альтернатива шаблону наблюдателя (за исключением, возможно, реактивного программирования, которое пока не распространено).

Я предлагаю использовать в качестве выражения watch функцию, которая возвращает хэш области. К сожалению, области содержат круговые ссылки где-то, поэтому быстрые решения, такие как JSON.stringify($scope), не работают. Я написал быстрое и грязное доказательство концепции. http://jsfiddle.net/ADukg/2544. Любое текстовое поле, которое вы вводите, печатает на консоли. Хеш-функция строки взята здесь Создает хэш из строки в Javascript/jQuery.

function MyCtrl($scope) {
    $scope.$watch(
        function($scope) {return hash($scope);},
        function() {console.log("changed");}
    );
}

Ответ 3

Я сам столкнулся с этой проблемой, и я решил ее с чем-то похожим на комментарий @ValentynShybanov, но не совсем то же самое. Мое решение не требует, чтобы вы префикс всех свойств, указанных в комментарии.

см. рабочий plunkr

var entireScope = {};
  for ( var i in $scope ){
    if ( i[0] !== '$' && i !== 'this' && i !== 'constructor'){
      console.log(i);
      entireScope[i] = $scope[i];
    }
  }

  $scope.entireScope = entireScope;

  $scope.$watch('entireScope', function( newValue, oldValue ){
   $log.info('entireScope has changed',newValue, oldValue);
  }, true);

поскольку вы видите, что решение совершенно одно и то же, но на самом деле оно добавляет другое свойство в область действия, а не заменяет структуру, которую у вас уже есть. это новое свойство представляет всю область действия (отсюда и ее название), и вы можете наблюдать за ней.

цикл, который я написал, может быть слишком общим, вы можете заменить его на персонализированную инициализацию. например:

$scope.entireScope = { 'someVal' : $scope.someVal }

это решение отвечает вашим потребностям и избавляет вас от необходимости реорганизовать код.

Ответ 4

Простое решение может заключаться в том, что вы должны проверять только переменную области, но это может быть и объект.

app.js

app.controller('MainController', ['$scope', function($scope){
   $scope.watchable = {
       'param1':'',
       'param2':''
   };
   $scope.update = -1;
   $scope.$watch('watchable', function(scope){
       scope.update++;
   }, true);

});

index.html

<div ng-controller="MainController">
    <input type='text' ng-model="watchable.param1">
    <input type='text' ng-model="watchable.param2">
    <p>param1:{{watchable.param1}}, param2:{{watchable.param2}}</p>
    <p>update:{{update}}
</div>

Трюк здесь состоит в том, чтобы передать "истину" в третьем параметре функции $watch, которая выполнит проверку angular.equal, которая проверяется по значению, а не простая контрольная проверка. Пожалуйста, дайте мне знать, если это правильно.