التنقل عبر الأنظمة الأساسية: لماذا هزم NavController الزاوي / الموجه في Ionic 4



مرحبا بالجميع! اسمي نيكيتا تشيجاموفسكي ، مبرمج في KitApp ، وأريد أن أتحدث عن تجربتي في بناء الملاحة في Ionic 4: المشكلة التي واجهتها وحلها.

أقوم بتطوير حلول عبر الأنظمة الأساسية للتطبيقات المحمولة منذ عام 2018. اعتدت أن أعمل على الإصدار الثالث من Ionic ، لكن مع مرور الوقت ، تتطور الوظيفة ، قررت التبديل إلى إصدار أحدث ، ويبدو أن اللحظات المزعجة والأخطاء في النموذج السابق في Ionic 4 قد تم إصلاحها بالفعل.

يبدو أن ما يمكن أن يحدث خطأ. أخيرًا ، لدينا وظيفة التوجيه الزاوي العادي ، وليس Nav Navroller القديم بكل أوجه القصور فيه. حتى على موقع Ionic الرسمي ، يشير دليل التوجيه إلى أن التنقل عبر الصفحات بطريقة برمجية أمر يستحق استخدام طرق الزاوي / جهاز التوجيه. ولكن كان هناك شيء ما جعلني أعود إلى NavController القديم.

جوهر المشكلة


وقد لوحظ وجود خطأ مثيرة للاهتمام. لنفترض أن لديك قائمة جانبية ، لقد قمت بإعدادها باستخدام جزء ion-split-pane. لديك أيضًا صفحات منفصلة من القائمة ، وتريد الانتقال منها إلى الصفحات الأخرى الموجودة في القائمة. انتقل باستخدام Router.navigateByUrl ('/ menu / ...'). بعد ذلك ، نسميه صفحة القائمة A ، والصفحة منفصلة عن القائمة - B. ولكن هناك واحد ولكن!

افترض ، في الصفحة أ ، أن هناك منطقًا معينًا يتم تشغيله في حدث ngOnInit. يمكنك الانتقال إلى الصفحة B باستخدام جهاز التوجيه ولاحظ أن صفحة القائمة لا تزال نشطة - لم يتم حذفها. وفقًا لذلك ، إذا عدت إلى الصفحة A ، فلن يعمل حدث ngOnInit ، لأن حدث ngOnDestroy في هذه الصفحة لم يعمل. يبدو أن كل شيء منطقي. في مثل هذه اللحظات ، لم يعد اللجوء إلى إحدى طرق دورة الحياة عادةً زاويًا ، بل هو ionViewWillEnter. تنطلق عندما تنتقل إلى الصفحة بمجرد أن تصبح نشطة. يبدو أن كل شيء على ما يرام ، إنه مناسب تمامًا ، لكن هناك عددًا معينًا من الاتفاقيات.

لن ينجح أي من الخيارات لاتخاذ إجراء مناسب في الصفحة "أ" عند الانتقال إليه ، إذا لم يكن هذا الانتقال من الصفحات الموجودة في القائمة. لن تتمكن من تتبع الانتقال إلى هذه الصفحة ، لأنني أكرر أنه ما زال مفتوحًا ويعمل بهدوء أسفل الصفحات الأخرى ، على سبيل المثال ، ضمن الصفحة B.

بعض الأمثلة التوضيحية:

ستعمل ionViewWillEnter إذا كان لديك بنية الصفحة التالية:

1) صفحات منفصلة

- page1
- page2
- page3

في هذا المثال ، عندما أذهب إلى كل صفحة ، ستعمل ionViewWillEnter بشكل مثالي. (page1 => page2 ، page2 => page3 ، إلخ)

2) القائمة / علامات التبويب

- القائمة
- menuPage1
- menuPage2
- menuPage3
في هذا المثال ، سيكون كل شيء على ما يرام: سيتم تشغيل طريقة ionViewWillEnter في كل مرة تذهب فيها إلى أي من الصفحات (menuPage1 => menuPage2 ، menuPage1 => menuPage3 ، وما إلى ذلك).

ولكن في المثال أدناه ، كل شيء أكثر تعقيدًا:

- القائمة
- menuPage1
- menuPage2
- menuPage3
- loginPage
- تسجيل الصفحة

هذا هو المكان الذي تبدأ فيه مشاكل التوجيه الزاوي القياسي. عند التنقل داخل صفحات القائمة (menuPage1 => menuPage2 => menuPage3) - ستعمل طريقة ionViewWillEnter كالمعتاد ، بنفس الطريقة عند التنقل بين الصفحات الفردية (loginPage => signupPage). ولكن بمجرد أن نبدأ في التنقل بين الصفحات المنفصلة وصفحات القائمة (loginPage => menu / menuPage1 أو menu / menuPage3 => signupPage) ، لا تعمل طريقة ngOnInit ولا ionViewWillEnter. لن تعمل ngOnInit لأنه لم يتم إتلاف الصفحة ، وهذا منطقي. ولكن لماذا لم ionViewWillEnter العمل؟

استنادًا إلى الوثائق ، يعمل ionViewWillEnter داخل مجموعات توجيه منفصلة (الكلمة الأساسية "فردية") أو بين صفحات فردية أو داخل قوائم / علامات تبويب. ولكن ليس في البنية المختلطة للصفحات الفردية والقوائم / علامات التبويب. غريب ، ولكن هذا يعتبر سلوكًا طبيعيًا. في الوقت نفسه ، ليس هذا هو بالضبط السلوك الذي يتوقعه المستخدمون ، لا سيما عندما تفكر في اسم خطافات دورة الحياة :).

فكيف لحل هذه المشكلة؟


بعد زيارة العديد من المنتديات ، ولكن دون رؤية حل طبيعي ، ورؤية العديد من المتسللين الذين لا ينجحون دائمًا في الحياة ، يصبح من الواضح أن هناك حاجة إلى شيء آخر. شيء من شأنه أن يغير وظيفة الانتقال بين الصفحات من أي نوع.

ماذا تفعل في هذه الحالة؟ بالطبع ، قم بتوجيه جهاز التوجيه إلى الجحيم ونسيانه ، لأنه لا يزال هناك من يكره سابقًا وهو NavController جيد جدًا.

الفرق الرئيسي بين طريقة NavController.navigateRoot () هو أنه بعد التبديل إلى صفحة أخرى ، يتم تدمير الصفحة السابقة تلقائيًا! وعند التبديل إليها مرة أخرى ، ستعمل كل من طريقة ngOnInit و ionViewWillEnter! في الواقع - هذا هو الحل الأمثل - بدون عكازات ووظائف مشبوهة مكتوبة ذاتياً.

أروع شيء هو أنه يعمل مع أي بنية للصفحة: حتى بين العادي ، حتى داخل القائمة ، وحتى الكتابة المختلطة ، كما في المثال الأخير.

تلخيص الجوانب الإيجابية:

  1. NavController يحذف الصفحة السابقة من المكدس ، على التوالي ، عند الرجوع إليها - يتم تحديثها ، تعمل أساليب ionViewWillEnter و ngOnInit ، ويمكنك الاتصال بالمنطق مرة أخرى وتحديث المعلومات الموجودة على الصفحات ، على سبيل المثال.
  2. ننسى طرق push () و setRoot () و pop () القديمة ، وكذلك التنقل عبر عناصر الفصل. بعد كل شيء ، كان هذا هو ما خلق الكثير من المشاكل. الآن navCtrl قام بتحديث الأساليب ، والتي يتم تمريرها بنفس المسار كما هو الحال في أساليب جهاز التوجيه.

هناك تحذير واحد ، حيث يمكنك الاستغناء عن "BUT" :)

إذا أضفنا معالج أحداث إلى زر "رجوع" للأجهزة على android وفي هذا المعالج حاولنا الذهاب إلى مكان ما باستخدام Router أو navController ، ثم حصلنا على الخطأ التالي في وحدة التحكم: "تم تشغيل التنقل خارج منطقة الزاوية".

نعم ، ستنجح عملية التنقل ، سيتم فتح الصفحة ، ولكن لن يعمل أي شيء - لا تهيئة الخصائص ولا أساليب دورة الحياة. لسوء الحظ ، يتم تشغيل التنقل عن طريق الضغط على زر الرجوع خارج منطقة الزاوي ، وفي الواقع ، يفتح القالب فقط: بدون متغيرات الربط إلى القالب ، دون وظائف ، والسنانير ، وطرق دورة الحياة - دون أي شيء.

الحل بسيط جدا ، في الواقع. نحن ببساطة فرض التنقل بوضوح داخل المنطقة الزاوي.

مثال:

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(); } 

والآن كل شيء يعمل بشكل جيد!

هناك العديد من المقالات المثيرة للاهتمام حول ngZone ، أنصحك أن تقرأ. حظا سعيدا

قليلا عن أساليب navController:



  • this.navCtrl.setDirection ('root') - يعيّن صفحة الجذر على الرصة ، مع حذف كل الملفات السابقة.
  • this.navCtrl.navigateRoot ('homePage') - يشبه navCtrl.setDirection ('root') + router.navigateByUrl ('homePage') ، ولكن مع الإزالة الإلزامية للصفحة السابقة في الحزمة (وهو ما نحتاج إليه).
  • this.navCtrl.navigateForward ('examplePage') - يشبه router.navigateByUrl ('/ examplePage) ، ولكن مع إشارة صريحة إلى أين تذهب + يمكن حذف الصفحة السابقة على المكدس.
  • this.navCtrl.back () - يشبه location.back () ، ولكن مع الرسوم المتحركة.
  • this.navCtrl.navigateBack ('backPage') - يشبه navCtrl.setDirection ('back') + router.navigateByUrl ('backPage').

لنفترض أننا الآن في القائمة / page1 ،

صورة

ولدينا مجموعة قائمة منفصلة ، وبعد الانتقال من menu / page1 إلى صفحة تسجيل الدخول ، نحتاج إلى حذف صفحة menu / page1 حتى بعد التبديل إليها مرة أخرى ، سيكون لدينا نوع من المنطق يعمل على ngOnInit أو ionViewWillEnter. إذا استخدمنا router.navigateByUrl ('تسجيل الدخول) للانتقال ، فبعد ذلك سنكون في صفحة تسجيل الدخول ، ولكن سيكون لدينا أيضًا صفحة قائمة ،



وفقًا لذلك ، بعد التبديل من تسجيل الدخول إلى القائمة / page1 ، لن تعمل ngOnInit ولا ionViewWillEnter.

إذا كنت تستخدم navCtrl.navigateRoot ('تسجيل الدخول') للتنقل ، فبعد فتح صفحة تسجيل الدخول ، يتم حذف الصفحة السابقة. وستعمل أساليب ngOnInit و ionViewWillEnter.



هذا هو جمال استخدام navController - السلوك المتوقع متوافق تمامًا مع التيار .

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


All Articles