Смотрите переменную и измените ее

В AngularJS у меня есть директива, которая отслеживает переменную области видимости. Когда переменная содержит определенные данные, мне нужно немного изменить эту переменную. Проблема заключается в том, что когда я изменяю переменную, которую мой $watch запускается снова. Поэтому я заканчиваю непрерывный цикл.

scope.$watch('someVar', function(newValue, oldValue) {
    console.log(newValue);
    scope.someVar = [Do something with someVar];
});

Это снова вызывает запуск $watch, что имеет смысл. Но мне нужен способ изменить наблюдаемую переменную. Есть ли способ сделать это?

Ответы

Ответ 1

Когда переменная просматривается для изменений с помощью $scope.$watch, angular проверяет, изменилась ли ссылка. Если он имеет, то обработчик $watch выполняется для обновления представления.

Если вы планируете изменить переменную области видимости в обработчике $watch, она вызовет цикл бесконечного цикла $digest, потому что ссылка переменной области изменяется каждый раз, когда она вызывается.

Трюк, чтобы обойти бесконечную проблему дайджеста, - сохранить ссылку внутри вашего обработчика $watch, используя angular.copy(docs):

scope.$watch('someVar', function(newValue, oldValue) {
    console.log(newValue);
    var someVar = [Do something with someVar];

    // angular copy will preserve the reference of $scope.someVar
    // so it will not trigger another digest 
    angular.copy(someVar, $scope.someVar);

});

Примечание. Этот трюк работает только для ссылок на объекты. Он не будет работать с примитивами.

В целом, не рекомендуется обновлять переменную $watched внутри своего собственного прослушивателя $watch. Однако иногда это может быть неизбежным.

Ответ 2

Внутри функции используется , если условие для продолжения продолжается для цикла

scope.$watch('someVar', function(newValue, oldValue) {
   if(newValue!==oldValue) {
    console.log(newValue);
    scope.someVar = [Do something with someVar];
   } 
});

Ответ 3

Вот как работает грязная проверка. Каждый раз, когда что-то на $scope меняет Angular, он будет вращаться по всему, что привязано к сфере действия, и будет продолжать делать это до тех пор, пока не будет никаких изменений.

Если вы хотите сделать что-то подобное, вам нужно убедиться, что ваша функция $watch является идемпотентной. Вам нужно будет посмотреть как newValue, так и oldValue и выяснить, что вы уже применили изменения к своей переменной в этом цикле $digest. Как вы можете это сделать, это немного зависит от того, какие изменения вы делаете с someVar.

Вообще говоря, изменение наблюдаемой переменной в функции часов, к сожалению, не очень хорошая идея.

Ответ 4

да, вы можете отменить его таким образом

var wathcer = scope.$watch('someVar', function(newValue, oldValue) {
    console.log(newValue);
    scope.someVar = [Do something with someVar];

});
wathcer(); // clear the watch

Ответ 5

вы можете управлять им с помощью переменной bool

$scope.someVarChanged = false;

scope.$watch('someVar', function(newValue, oldValue) {
    console.log(newValue);
    $scope.someVarChanged = !$scope.someVarChanged!;
    if($scope.someVarChanged) {            
        scope.someVar = [Do something with someVar];
    }
});