Angular.js: Pengontrol mengaitkan pesanan ($onChanges dipanggil sebelum $onInit)

Dibuat pada 16 Des 2016  ·  9Komentar  ·  Sumber: angular/angular.js

Apakah Anda ingin meminta fitur atau melaporkan bug ?
Saya tidak tahu apakah itu diinginkan atau apakah itu bug

Apa perilaku saat ini?
Panggilan $onChanges dilakukan sebelum panggilan $onInit .
Dengan konfigurasi default sudut 1.6 (preassign = false), lebih disukai untuk menginisialisasi status pengontrol dalam fungsi $onInit , mengingat binding belum dapat diakses di konstruktor.

Apa perilaku yang diharapkan?
Saya pikir akan lebih logis untuk memanggil $onInit terlebih dahulu.
Angular tidak boleh melakukan apa pun saat pengontrol tidak sepenuhnya diinisialisasi.

Apa motivasi / kasus penggunaan untuk mengubah perilaku?
Jika kita menggunakan objek yang seharusnya dibuat dalam fungsi $onInit dalam fungsi $onChanges ; kita akan mengalami kesalahan pada panggilan pertama, karena pengontrol belum diinisialisasi.
Solusinya adalah menginisialisasi objek-objek tersebut di dalam konstruktor, tetapi kita akan menginisialisasi pengontrol di dua tempat berbeda...

Versi Angular mana, dan browser/OS mana yang terpengaruh oleh masalah ini? Harap uji juga dengan versi stabil dan snapshot (https://code.angularjs.org/snapshot/) terbaru.
versi 1.6 sudut

works as expected

Komentar yang paling membantu

Ini dimaksudkan (terutama untuk mencocokkan perilaku Angular 2+). Jika Anda melewatkannya, Anda dapat memeriksa apakah itu panggilan (pra-$onInit) pertama dari $onChanges , dengan memeriksa nilai kembalian metode isFirstChange() dari salah satu SimpleChange objek:

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

#

Saya akui bahwa reaksi pertama saya sama. Dari perspektif model mental lebih mudah untuk berpikir $onInit() adalah hal pertama yang terjadi di controller; lalu $onChanges() , $onChanges() , $onChanges() dan akhirnya $onDestroy() .

Tetapi jika Anda memikirkannya, binding perlu dievaluasi dan ditetapkan ke instance controller sebelum memanggil $onInit . Dan dengan melakukannya, perubahan nilai (sebelumnya tidak ditentukan) terdeteksi, yang pada gilirannya perlu dilaporkan melalui $onChanges .

Penutupan, karena ini berfungsi seperti yang diharapkan (atau setidaknya seperti yang dimaksudkan :wink :).

Semua 9 komentar

Ini dimaksudkan (terutama untuk mencocokkan perilaku Angular 2+). Jika Anda melewatkannya, Anda dapat memeriksa apakah itu panggilan (pra-$onInit) pertama dari $onChanges , dengan memeriksa nilai kembalian metode isFirstChange() dari salah satu SimpleChange objek:

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

#

Saya akui bahwa reaksi pertama saya sama. Dari perspektif model mental lebih mudah untuk berpikir $onInit() adalah hal pertama yang terjadi di controller; lalu $onChanges() , $onChanges() , $onChanges() dan akhirnya $onDestroy() .

Tetapi jika Anda memikirkannya, binding perlu dievaluasi dan ditetapkan ke instance controller sebelum memanggil $onInit . Dan dengan melakukannya, perubahan nilai (sebelumnya tidak ditentukan) terdeteksi, yang pada gilirannya perlu dilaporkan melalui $onChanges .

Penutupan, karena ini berfungsi seperti yang diharapkan (atau setidaknya seperti yang dimaksudkan :wink :).

Terima kasih banyak atas jawabannya, sekarang lebih jelas :)

Saya mengerti ini disengaja, bagaimana jika kita mendaftarkan definisi fungsi $onChanges() di dalam $onInit().

@bharatpatil , itu harus bekerja di AngularJS (1.x.) tetapi tidak akan di Angular (2+).

if (changes.foo.isFirstChange()) {
// $onInit() belum dipanggil...
}

@gkalpak Saya pikir argumen ini salah. binding.isFirstChange() metode hanya menjamin bahwa pengikatan terkait dipanggil pertama kali. Pikirkan pengikatan yang diinisialisasi setelah panggilan layanan membutuhkan waktu terlalu lama. Dalam situasi ini metode controller.$onInit harus dipanggil sebelum metode controller.$onChanges . Apakah aku salah?

Pengikatan selalu memiliki nilai di awal (bisa undefined ), yang selalu berbeda dengan nilai pra-inisialisasinya. Jadi, $onChanges() akan selalu dipanggil dengan changes.foo sebelum memanggil $onInit() .

Tidak masuk akal secara logis bahwa pengikatan dapat memiliki nilai sebelum diinisialisasi. Seperti itu penjelasan definisi sebenarnya dari kata initialise (mengatur nilai awal). Anda tidak dapat mengubah sesuatu jika tidak memiliki nilai awal. Saya pikir penamaan semua salah di sini dan tidak wajar.

Saya tidak dapat mengingat situasi di mana saya tidak dipaksa untuk menulis sesuatu seperti kode ini:

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

Memanggil "perubahan" sebelum "inisialisasi" tidak masuk akal.

Setara dengan kursus dengan Angular... mengapa ada orang yang mengharapkan init terjadi sebelum perubahan?

Apakah halaman ini membantu?
0 / 5 - 0 peringkat