Saya memiliki komponen induk ( CategoryComponent ), komponen anak ( videoListComponent ) dan ApiService.
Saya memiliki sebagian besar ini berfungsi dengan baik yaitu setiap komponen dapat mengakses json api dan mendapatkan data yang relevan melalui yang bisa diamati.
Saat ini komponen daftar video baru saja mendapatkan semua video, saya ingin memfilter ini untuk hanya video dalam kategori tertentu, saya mencapai ini dengan meneruskan kategoriId ke anak melalui @Input()
.
CategoryComponent.html
<video-list *ngIf="category" [categoryId]="category.id"></video-list>
Ini berfungsi dan ketika kategori induk CategoryComponent berubah maka nilai CategoryId akan dilewati, @Input()
tetapi saya kemudian perlu mendeteksi ini di VideoListComponent dan meminta kembali array video melalui APIService (dengan CategoryId baru).
Di AngularJS saya akan melakukan $watch
pada variabel. Apa cara terbaik untuk menangani ini?
sumber
Jawaban:
Sebenarnya, ada dua cara untuk mendeteksi dan bertindak ketika input berubah dalam komponen anak di angular2 +:
Tautan Dokumentasi: ngOnChanges, SimpleChanges, SimpleChange
Demo Contoh: Lihat plunker ini
Tautan Dokumentasi: Lihat di sini .
Contoh Demo: Lihat plunker ini .
PENDEKATAN APA YANG HARUS ANDA GUNAKAN?
Jika komponen Anda memiliki beberapa input, maka, jika Anda menggunakan ngOnChanges (), Anda akan mendapatkan semua perubahan untuk semua input sekaligus dalam ngOnChanges (). Dengan menggunakan pendekatan ini, Anda juga dapat membandingkan nilai input saat ini dan sebelumnya yang telah berubah dan mengambil tindakan yang sesuai.
Namun, jika Anda ingin melakukan sesuatu ketika hanya satu input tertentu yang berubah (dan Anda tidak peduli dengan input lainnya), maka mungkin lebih mudah untuk menggunakan setter properti input. Namun, pendekatan ini tidak menyediakan cara bawaan untuk membandingkan nilai sebelumnya dan saat ini dari input yang diubah (yang dapat Anda lakukan dengan mudah dengan metode siklus hidup ngOnChanges).
EDIT 2017-07-25: DETEKSI PERUBAHAN ANGULAR MUNGKIN MASIH TIDAK KEBAKARAN DI BAWAH BEBERAPA SIRKUMSTAN
Biasanya, deteksi perubahan untuk penyetel dan ngOnChanges akan diaktifkan setiap kali komponen induk mengubah data yang dilewatinya kepada anak, asalkan data tersebut adalah tipe data primitif JS (string, number, boolean) . Namun, dalam skenario berikut, itu tidak akan menyala dan Anda harus mengambil tindakan tambahan untuk membuatnya berfungsi.
Jika Anda menggunakan objek atau array bersarang (alih-alih tipe data primitif JS) untuk meneruskan data dari Induk ke Anak, ubah deteksi (menggunakan penyetel atau ngchanges) mungkin tidak diaktifkan, seperti juga disebutkan dalam jawaban oleh pengguna: muetzerich. Untuk solusinya lihat di sini .
Jika Anda memutasikan data di luar konteks sudut (yaitu, secara eksternal), maka sudut tidak akan mengetahui perubahan. Anda mungkin harus menggunakan ChangeDetectorRef atau NgZone di komponen Anda untuk membuat sudut menyadari perubahan eksternal dan karenanya memicu deteksi perubahan. Lihat ini .
sumber
doSomething
metode Anda dan mengambil 2 argumen nilai baru dan lama sebelum benar-benar menetapkan nilai baru, dengan cara lain akan menyimpan nilai lama sebelum menetapkan dan memanggil metode setelah itu.Gunakan
ngOnChanges()
metode siklus hidup di komponen Anda.Berikut adalah Documents .
sumber
MyComponent.myArray = []
, Tetapi jika nilai input diubah misalnyaMyComponent.myArray.push(newValue)
,ngOnChanges()
tidak dipicu. Ada ide tentang cara menangkap perubahan ini?ngOnChanges()
tidak dipanggil ketika objek bersarang telah berubah. Mungkin Anda menemukan solusinya di siniSaya mendapatkan kesalahan di konsol serta kompiler dan IDE saat menggunakan
SimpleChanges
tipe pada fungsi signature. Untuk mencegah kesalahan, gunakanany
kata kunci dalam tanda tangan sebagai gantinya.EDIT:
Seperti yang ditunjukkan Jon di bawah ini, Anda dapat menggunakan
SimpleChanges
tanda tangan saat menggunakan notasi braket daripada notasi titik.sumber
SimpleChanges
antarmuka di bagian atas file Anda?<my-user-details [user]="selectedUser"></my-user-details>
). Properti ini diakses dari kelas SimpleChanges dengan meneleponchanges.user.currentValue
. Pemberitahuanuser
terikat pada saat runtime dan bukan bagian dari objek SimpleChangesngOnChanges(changes: {[propName: string]: SimpleChange}) { console.log('onChanges - myProp = ' + changes['myProp'].currentValue); }
Taruhan paling aman adalah menggunakan layanan bersama alih - alih
@Input
parameter. Juga,@Input
parameter tidak mendeteksi perubahan dalam tipe objek bersarang yang kompleks.Contoh layanan sederhana adalah sebagai berikut:
Anda dapat menggunakan implementasi yang serupa di komponen lain dan semua komponen Anda akan berbagi nilai bersama yang sama.
sumber
@Input
Parameter @JoshuaKemmerer tidak mendeteksi perubahan dalam tipe objek bersarang yang kompleks tetapi dalam objek asli yang sederhana.Saya hanya ingin menambahkan bahwa ada kait Lifecycle lain yang disebut
DoCheck
yang berguna jika@Input
nilainya bukan nilai primitif.Saya memiliki Array sebagai
Input
sehingga ini tidak memecatOnChanges
acara ketika konten berubah (karena pengecekan yang dilakukan Angular adalah 'sederhana' dan tidak dalam sehingga Array masih merupakan Array, meskipun konten pada Array telah berubah).Saya kemudian menerapkan beberapa kode pemeriksaan khusus untuk memutuskan apakah saya ingin memperbarui tampilan saya dengan Array yang diubah.
sumber
silakan coba menggunakan metode ini. Semoga ini membantu
sumber
Anda juga dapat, memiliki yang dapat diamati yang memicu perubahan pada komponen induk (CategoryComponent) dan melakukan apa yang ingin Anda lakukan dalam berlangganan komponen anak. (videoListComponent)
sumber
Di sini ngOnChanges akan selalu memicu ketika properti input Anda berubah:
sumber
Solusi ini menggunakan kelas proxy dan menawarkan keuntungan berikut:
ngOnChanges()
Contoh penggunaan:
Fungsi utilitas:
sumber
Jika Anda tidak ingin menggunakan metode og onChange () implement ngOnChange, Anda juga dapat berlangganan perubahan item tertentu dengan event valueChanges , ETC.
});
the markForCheck () writen karena menggunakan dalam menyatakan ini:
sumber
Anda juga bisa hanya melewatkan EventEmitter sebagai Input. Tidak yakin apakah ini praktik terbaik ...
CategoryComponent.ts:
CategoryComponent.html:
Dan di VideoListComponent.ts:
sumber