Почему AngularJS $ onChanges не замечает, что массив изменился? - PullRequest
0 голосов
/ 01 января 2019

Почему Angular не замечает, что массив изменился, но если я сначала изменю его на NULL?

У меня есть компонент AngularJS, который принимает массив через в одну сторону двух-способ (=) привязки данных.У родителя у меня есть кнопка, чей щелчок по нг соответствует этой функции:

onClickAddValue()
{ 
    this.listOfValues.push(this.valueInput);
}

, где this.listOfValues - это то, что передается дочернему компоненту через привязку.Этот код не имеет никакого эффекта (представление дочернего компонента не обновляется).Будучи умным cookie, который заранее сделал домашнее задание по AngularJS, я знаю, что это потому, что значение listOfValues не изменилось, это все та же ссылка на объект.Поэтому я делаю это:

onClickAddValue()
{ 
    var oldList = this.listOfValues;
    this.listOfValues = [];
    for (let value of oldList)
    {
        this.listOfValues.push(value);
    }
    this.listOfValues.push(this.valueInput);
}

Но это тоже не работает!Я также пытался Object.assign и angular.copy.Как будто мой дочерний компонент просто не замечает никаких изменений в его входных данных вообще.И все же ясно, что это так, потому что код ниже работает !

onClickAddValue()
{ 
    var oldList = this.listOfValues;
    this.listOfValues = null;
    setTimeout(
        () =>
        {
            this.listOfValues = oldList;
            this.listOfValues.push(this.valueInput);
            this.$scope.$digest();
        }
    );  
}

Что происходит?Я могу понять, почему последний фрагмент работает - listOfValues имеет значение NULL, ng-click автоматически запускает дайджест, и Angular замечает новое значение NULL, поэтому он обновляет представление, а затем мгновенное изменение listOfValues снова изменяется,другой дайджест запускается вручную, и представление обновляется снова.Но тогда почему другая версия не работает?Почему изменение объекта отличается от изменения его на ноль, а затем его изменение?

1 Ответ

0 голосов
/ 06 января 2019

Я слушаю изменения для границы listOfValues в $onChanges

Используйте Array.concat , чтобы создать новый объект, который будет$onChanges:

  onClickAddValue()
  { 
    this.listOfValues.push(this.valueInput);
    this.listOfValues = this.listOfValues.concat();
  }

$onChanges Крюк жизненного цикла проверяет только изменения эталон .Он не проверяет наличие содержимого изменений.После изменения содержимого на Array.push.Используйте метод Array.concat, чтобы создать новый объект, который будет обнаружен детектором изменений.

DEMO

angular.module("app",[])
.controller("ctrl", class {
  constructor () {
    this.listOfValues = [3,5];
  }
  onClickAddValue()
  { 
    this.listOfValues.push(this.valueInput);
    this.listOfValues = this.listOfValues.concat();
  }
})
.component("myComponent",{
  bindings: {values: "<"},
  template: `
      <fieldset>
        {{$ctrl.values}}<br>
        changes={{$ctrl.changes}}
      </fieldset>
  `,
  controller: class {
    constructor () {
      this.changes=0;
    }
    $onChanges(ch) {
      this.changes++;
      //console.log(ch);
    }
  }
})
<script src="//unpkg.com/angular/angular.js"></script>
<body ng-app="app" ng-controller="ctrl as $ctrl">
    <input ng-model="$ctrl.valueInput" /><br>
    <button ng-click="$ctrl.onClickAddValue()">Add value</button>
    <br>
    {{$ctrl.listOfValues}}
    <my-component values="$ctrl.listOfValues"></my-component>
</body>

Обновление

Поработав, я думаю, это на самом деле связано с тем, что listOfValues привязан к дочернему компоненту с привязкой =, а не с привязкой < - изменение на привязку < приводит к ее внезапной работе

Документация для $ngChanges четко гласитчто он работает с атрибутами ('@') и односторонними ('<') привязками.

Из документов:

Перехватчики жизненного цикла

  • $onChanges(changesObj) - Вызывается всякий раз, когда обновляются односторонние (<) или интерполяционные (@) привязки.changesObj - это хеш, ключи которого - это имена связанных свойств, которые изменились, а значения - это объект вида { currentValue, previousValue, isFirstChange() }.Используйте этот хук для запуска обновлений внутри компонента, таких как клонирование связанного значения, чтобы предотвратить случайную мутацию внешнего значения.Обратите внимание, что это также будет вызываться при инициализации ваших привязок.

- Справочник по API AngularJS - Ссылка на полный цикл жизненного цикла

Двух-Следует избегать связывания ("="), поскольку он добавляет дополнительный наблюдатель и усложняет переход на Angular 2+.

Для получения дополнительной информации см. Руководство разработчика AngularJS - Архитектура приложений на основе компонентов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...