Navigasi lintas platform: mengapa NavController mengalahkan angular / router di Ionic 4



Halo semuanya! Nama saya Nikita Zhigamovsky, seorang programmer di KitApp, dan saya ingin berbicara tentang pengalaman saya dalam membangun navigasi di Ionic 4: masalah yang saya temui dan solusinya.

Saya telah mengembangkan solusi lintas platform untuk aplikasi seluler sejak 2018. Saya dulu bekerja pada Ionic versi 3, tetapi, seiring berjalannya waktu, fungsionalitas berkembang, saya memutuskan untuk beralih ke versi yang lebih baru, dan saat-saat yang mengganggu dan bug dari model sebelumnya di Ionic 4 tampaknya sudah diperbaiki.

Tampaknya apa yang bisa salah. Akhirnya, kami memiliki fungsi perutean Angular normal, dan bukan NavController lama dengan semua kekurangannya. Bahkan di situs web resmi Ionic, panduan perutean menunjukkan bahwa navigasi program melalui halaman layak menggunakan metode sudut / router. Tetapi ada sesuatu yang membuat saya kembali ke NavController lama.

Inti dari masalah


Bug yang menarik diperhatikan. Misalkan Anda memiliki menu samping, Anda membuatnya menggunakan ion-split-pane. Anda juga memiliki halaman terpisah dari menu, dan Anda ingin beralih dari halaman tersebut ke halaman lain yang ada di menu. Navigasi menggunakan Router.navigateByUrl ('/ menu / ...'). Selanjutnya, kita sebut halaman menu A, dan halaman terpisah dari menu - B. Tapi ada satu TETAPI!

Misalkan, pada halaman A, logika tertentu dipicu dalam acara ngOnInit. Anda menavigasi ke halaman B menggunakan Router dan perhatikan bahwa halaman menu masih aktif - itu belum dihapus. Dengan demikian, jika Anda kembali ke halaman A, acara ngOnInit tidak akan berfungsi, karena acara ngOnDestroy halaman ini tidak berfungsi. Tampaknya semuanya logis. Pada saat-saat seperti itu, mereka biasanya menggunakan salah satu metode siklus hidup, bukan sudut, tetapi ion-ionViewWillEnter. Itu menyala ketika Anda pergi ke halaman segera setelah itu menjadi aktif. Segalanya tampak baik-baik saja, sangat pas, tetapi ada sejumlah konvensi.

Tak satu pun dari opsi untuk tindakan yang memadai pada halaman A akan berfungsi ketika pergi ke sana, jika transisi ini bukan dari halaman yang ada di menu. Anda tidak akan dapat melacak transisi ke halaman ini, karena, saya ulangi, itu masih terbuka dan berfungsi dengan tenang di bawah halaman lain, misalnya, di bawah halaman B.

Beberapa contoh ilustrasi:

ionViewWillEnter akan berfungsi jika Anda memiliki struktur halaman berikut:

1) Pisahkan halaman

- halaman1
- halaman2
- halaman3

Dalam contoh ini, ketika saya pergi ke setiap halaman, ionViewWillEnter akan bekerja dengan sempurna. (halaman1 => halaman2, halaman2 => halaman3, dll.)

2) Menu / Tab

- menu
- menuPage1
- menuPage2
- menuPage3
Dalam contoh ini, semuanya juga akan baik-baik saja: metode ionViewWillEnter akan diaktifkan setiap kali Anda pergi ke halaman mana saja (menuPage1 => menuPage2, menuPage1 => menuPage3, dll.).

Namun dalam contoh di bawah ini, semuanya lebih rumit:

- menu
- menuPage1
- menuPage2
- menuPage3
- loginPage
- signupPage

Di sinilah masalah standar Angular routing dimulai. Saat menavigasi halaman menu di dalam (menuPage1 => menuPage2 => menuPage3) - metode ionViewWillEnter akan berfungsi seperti biasa, dengan cara yang sama ketika menavigasi antara halaman individual (loginPage => signupPage). Tetapi segera setelah kami mulai bergerak antara halaman yang terpisah dan halaman menu (loginPage => menu / menuPage1 atau menu / menuPage3 => signupPage), baik metode ngOnInit maupun ionViewWillEnter tidak berfungsi. ngOnInit tidak akan berfungsi karena halaman belum dihancurkan, yang logis. Tetapi mengapa ionViewWillEnter tidak berfungsi?

Berdasarkan dokumentasi, ionViewWillEnter bekerja di dalam tumpukan perutean yang terpisah (kata kunci "individu") atau antara halaman-halaman individual, atau di dalam menu / tab. Tetapi tidak dalam struktur campuran dari masing-masing halaman dan menu / tab. Aneh, tetapi ini dianggap perilaku normal. Pada saat yang sama, ini bukan perilaku yang diharapkan pengguna, terutama ketika Anda mempertimbangkan nama kait siklus hidup :).

Lantas bagaimana cara mengatasi masalah ini?


Setelah mengunjungi banyak forum, tetapi tidak melihat solusi normal, dan melihat beberapa peretas kehidupan yang meragukan yang tidak selalu berhasil, menjadi jelas bahwa ada sesuatu yang lain yang diperlukan. Sesuatu yang akan mengubah fungsi transisi antar halaman dari jenis apa pun.

Apa yang harus dilakukan dalam kasus ini? Tentu saja, buang Router ke neraka dan lupakan saja, karena masih ada NavController yang sebelumnya kita benci dan sekarang begitu baik.

Perbedaan utama antara metode NavController.navigateRoot () adalah bahwa setelah beralih ke halaman lain, yang sebelumnya secara otomatis dihancurkan! Dan ketika Anda beralih lagi, metode ngOnInit dan ionViewWillEnter akan berfungsi! Bahkan - ini adalah solusi sempurna - tanpa kruk dan fungsi penulisan sendiri yang meragukan.

Yang paling keren adalah ia bekerja dengan struktur halaman apa pun: bahkan di antara normal, bahkan di dalam menu, bahkan tipe campuran, seperti dari contoh terakhir.

Ringkaslah aspek-aspek positif:

  1. NavController menghapus halaman sebelumnya dari tumpukan, masing-masing, ketika Anda kembali ke sana - itu diperbarui, metode ionViewWillEnter dan ngOnInit bekerja, dan Anda dapat memanggil logika di dalamnya lagi dan memperbarui informasi pada halaman, misalnya.
  2. Lupakan metode push lama (), setRoot (), dan pop (), serta navigasi melalui elemen kelas. Bagaimanapun, inilah yang menciptakan banyak masalah. Sekarang navCtrl telah memperbarui metode, yang melewati jalur yang sama seperti pada metode Router.

Ada satu peringatan, di mana tanpa "TAPI" :)

Jika kita menambahkan event handler ke tombol “back” perangkat keras pada android dan di handler ini kita mencoba pergi ke suatu tempat menggunakan Router atau navController, maka kita mendapatkan kesalahan berikut di konsol: 'Navigasi terpicu di luar zona Angular'.

Ya, navigasi akan berfungsi, halaman akan terbuka, tetapi tidak ada yang berfungsi - baik inisialisasi properti, maupun metode siklus hidup. Sayangnya, navigasi dengan menekan tombol kembali dipicu di luar zona Angular dan, pada kenyataannya, hanya membuka templat: tanpa variabel yang mengikat pada templat, tanpa fungsi, kait, metode siklus hidup - tanpa apa pun.

Solusinya sebenarnya sangat sederhana. Kami hanya secara eksplisit memaksa navigasi di dalam zona Angular.

Contoh:

import { Component, NgZone } from '@angular/core'; import { NavController } from '@ionic/angular'; @Component({ selector: 'app-root', templateUrl: 'app.component.html' }) export class AppComponent { constructor(private navCtrl: NavController, private ngZone: NgZone){} this.ngZone.run(() => this.navCtrl.navigateForward('menu')).then();  this.ngZone.run(() => this.router.navigateByUrl('/menu/my-orders')).then(); } 

Dan sekarang semuanya bekerja dengan baik!

Ada banyak artikel menarik tentang ngZone, saya sarankan Anda baca. Semoga beruntung

Sedikit tentang metode navController:



  • this.navCtrl.setDirection ('root') - mengatur halaman root pada stack, menghapus semua yang sebelumnya.
  • this.navCtrl.navigateRoot ('homePage') - mirip dengan navCtrl.setDirection ('root') + router.navigateByUrl ('homePage'), tetapi dengan penghapusan wajib dari halaman sebelumnya pada stack (yang kita butuhkan).
  • this.navCtrl.navigateForward ('examplePage') - mirip dengan router.navigateByUrl ('/ examplePage), tetapi dengan indikasi eksplisit ke mana harus pergi + dapat menghapus halaman sebelumnya di stack.
  • this.navCtrl.back () - mirip dengan location.back (), tetapi dengan animasi.
  • this.navCtrl.navigateBack ('backPage') - mirip dengan navCtrl.setDirection ('back') + router.navigateByUrl ('backPage').

Misalkan kita sekarang pada menu / halaman1,

gambar

dan kami memiliki tumpukan menu yang terpisah dan, setelah beralih dari menu / page1 ke halaman login, kita perlu menghapus menu / page1 halaman sehingga setelah beralih lagi, kita akan memiliki beberapa jenis logika yang bekerja pada ngOnInit atau ionViewWillEnter. Jika kita menggunakan router.navigateByUrl ('login) untuk transisi, maka setelah itu kita akan berada di halaman login, tetapi kita juga akan memiliki halaman menu,



karenanya, setelah beralih dari login ke menu / page1, ngOnInit atau ionViewWillEnter tidak akan berfungsi.

Jika Anda menggunakan navCtrl.navigateRoot ('login') kami untuk bernavigasi, maka setelah membuka halaman login, halaman sebelumnya dihapus. Dan metode ngOnInit dan ionViewWillEnter akan berfungsi.



Ini adalah keindahan menggunakan navController - perilaku yang diharapkan sepenuhnya konsisten dengan saat ini .

Source: https://habr.com/ru/post/id473488/


All Articles