Angular.js: Порядок перехватов контроллеров ($ onChanges вызывается до $ onInit)

Созданный на 16 дек. 2016  ·  9Комментарии  ·  Источник: angular/angular.js

Вы хотите запросить функцию или сообщить об ошибке ?
Я не знаю, нужно ли это или это ошибка

Каково текущее поведение?
Первый вызов $onChanges выполняется до $onInit one.
С конфигурацией по умолчанию angular 1.6 (preassign = false) предпочтительно инициализировать состояния контроллера в функции $onInit , поскольку привязки еще не доступны в конструкторе.

Какое ожидаемое поведение?
Думаю, логичнее было бы сначала назвать $onInit .
Angular не должен ничего делать, пока контроллер не полностью инициализирован.

Какова мотивация / вариант использования для изменения поведения?
Если мы используем объекты, которые должны быть созданы в функции $onInit в $onChanges function; у нас будет ошибка при первом вызове, потому что контроллер еще не инициализирован.
Решением может быть инициализация этих объектов внутри конструктора, но мы инициализируем контроллер в двух разных местах ...

Какие версии Angular и какой браузер / ОС подвержены этой проблеме? Также проверьте последнюю стабильную версию и версию моментального снимка (https://code.angularjs.org/snapshot/).
угловая версия 1.6

works as expected

Самый полезный комментарий

Это предназначено (в основном, чтобы соответствовать поведению Angular 2+). Если вы его пропустили, вы можете проверить, является ли это первым (до $ onInit) вызовом $onChanges , проверив возвращаемое значение метода isFirstChange() любого из SimpleChange объекты:

{
  ...
  bindings: {foo: '<'},
  controller: function SomeController() {
    this.$onChanges = function(changes) {
      if (changes.foo.isFirstChange()) {
        // `$onInit()` has not been called yet...
      }
    };
  }
}

#

Признаюсь, моя первая реакция была такой же. С точки зрения ментальной модели легче думать, что $onInit() - это первое, что происходит в контроллере; затем $onChanges() , $onChanges() , $onChanges() и, наконец, $onDestroy() .

Но если подумать, привязки необходимо оценить и присвоить экземпляру контроллера перед вызовом $onInit . Таким образом, обнаруживается изменение (ранее не заданных) значений, о котором, в свою очередь, необходимо сообщить через $onChanges .

Закрытие, так как это работает, как ожидалось (или, по крайней мере, как задумано: wink :).

Все 9 Комментарий

Это предназначено (в основном, чтобы соответствовать поведению Angular 2+). Если вы его пропустили, вы можете проверить, является ли это первым (до $ onInit) вызовом $onChanges , проверив возвращаемое значение метода isFirstChange() любого из SimpleChange объекты:

{
  ...
  bindings: {foo: '<'},
  controller: function SomeController() {
    this.$onChanges = function(changes) {
      if (changes.foo.isFirstChange()) {
        // `$onInit()` has not been called yet...
      }
    };
  }
}

#

Признаюсь, моя первая реакция была такой же. С точки зрения ментальной модели легче думать, что $onInit() - это первое, что происходит в контроллере; затем $onChanges() , $onChanges() , $onChanges() и, наконец, $onDestroy() .

Но если подумать, привязки необходимо оценить и присвоить экземпляру контроллера перед вызовом $onInit . Таким образом, обнаруживается изменение (ранее не заданных) значений, о котором, в свою очередь, необходимо сообщить через $onChanges .

Закрытие, так как это работает, как ожидалось (или, по крайней мере, как задумано: wink :).

Большое спасибо за ответ, теперь понятнее :)

Я понимаю, что это сделано намеренно, как насчет того, чтобы зарегистрировать определение функции $ onChanges () внутри $ onInit ().

@bharatpatil , он должен работать в AngularJS (1.x.), но не в Angular (2+).

if (changes.foo.isFirstChange ()) {
// $onInit() еще не был вызван ...
}

@gkalpak Я считаю, что это неверный аргумент. Метод binding.isFirstChange() гарантирует только то, что связанная привязка была вызвана в первый раз. Подумайте о привязке, которая инициализируется после того, как вызов службы занимает слишком много времени. В этой ситуации метод controller.$onInit следует вызывать перед методом controller.$onChanges . Я ошибся?

Привязка всегда имеет значение в начале (может быть undefined ), которое всегда отличается от его предварительно инициализированного значения. Таким образом, $onChanges() всегда будет вызываться с changes.foo перед вызовом $onInit() .

Нет логического смысла в том, что привязка может иметь значение до ее инициализации. Это словарное определение слова инициализировать (установить начальные значения). Вы не можете что-то изменить, если у него не было начального значения. Я думаю, что названия здесь неправильные и неестественные.

Я не могу вспомнить ситуацию, когда меня не заставляли писать что-то вроде этого кода:

$onChanges(changesObj: { [index: string]: angular.IChangesObject; })  {
   if (!this.isInitialized) return;
   ...
}

Вызов «изменений» перед «инициализацией» не имеет никакого смысла.

Параллельно с Angular ... почему кто-то может ожидать, что init произойдет до изменений?

Была ли эта страница полезной?
0 / 5 - 0 рейтинги