التغييرات التي طرأت على حدث ScrollEvent في Chrome 105

Joe Medley
Joe Medley

يقدّم الإصدار 105 من Chrome طريقتَين جديدتَين في NavigateEvent لواجهة برمجة التطبيقات Navigation API (التي تم تقديمها في الإصدار 102) لتحسين الطرق التي تبيّن أنّها تسبب مشاكل في الممارسة. يحلّ الإجراء intercept() محلّ الإجراء transitionWhile() الذي تبيّن أنّه صعب الاستخدام، ويسمح للمطوّرين بالتحكم في الحالة بعد التنقّل. تستبدل طريقة scroll()، التي تنتقل إلى إشارة مرجعية محدّدة في عنوان URL، طريقة restoreScroll() التي لا تعمل مع جميع أنواع التنقّل.

في هذه المقالة، سأوضّح المشاكل المتعلّقة بكلتا الطريقتَين وكيفية حلّها باستخدام الطرق الجديدة.

تؤدي طريقة NavigateEvent.trasitionWhile()، التي تم تقديمها مع Navigation API في الإصدار 102 من Chrome، إلى اعتراض عمليات التنقّل في عمليات النقل من جهة العميل في تطبيقات الصفحة الواحدة. الوسيطة الأولى هي وعد يشير إلى المتصفّح وأجزاء أخرى من تطبيق الويب بأنّه قد اكتمل.

لم يحقّق هذا الإجراء نتائج جيدة في الممارسة. راجِع نمط الترميز الشائع التالي:

event.transitionWhile((async () => {
  doSyncStuff();
  await doAsyncStuff();
})());

وهذا مكافئ وظيفيًا للرمز البرمجي أدناه. ويؤدي ذلك إلى تنفيذ جزء من عملية التنقّل قبل أن تدرك واجهة برمجة التطبيقات أنّ المطوّر يريد اعتراض عملية التنقّل.

doSyncStuff();
event.transitionWhile((async () => {
  await doAsyncStuff();
})());

على سبيل المثال، يمكن أن يؤدي ذلك إلى حدوث خلل في التطبيق في ما يتعلّق بمنطق استعادة الانتقال للأعلى أو للأسفل، حيث يتم تسجيل مواضع الانتقال للأعلى أو للأسفل بعد تغيير نموذج DOM بدلاً من قبله.

التغييرات التي أُجريت

لاستبدال transitionWhile()، تُقدّم المواصفة الحالية NavigateEvent.intercept(). تأخذ الطريقة الجديدة معالِجًا بالإضافة إلى السمتَين focusReset وscrollRestoration المتوافقتَين مع transitionWhile(). يتم تنفيذ المعالج الجديد دائمًا بعد اكتمال التنقّل، ويتم تسجيل عناصر مثل مواضع التمرير، ما يتجنّب المشاكل المتعلّقة بـ transitionWhile().

لا تزال طريقة transitionWhile() متاحة، ولكن تم إيقافها نهائيًا وستتم إزالتها في الإصدار 108 من Chrome.

استخدام دالة intercept()‎

تسري القيود نفسها على NavigateEvent.intercept() مثل transitionWhile()، إذ لا يمكن استدعاؤه في جميع أحداث التنقّل. لا يمكن اعتراض عمليات التنقّل بين مصادر مختلفة، ولا يمكن أيضًا عبور المستندات المختلفة. سيؤدي ذلك إلى طرح DOMException من النوع "SecurityError".

لاستخدام intercept()، ما عليك سوى تمرير معالِجك المخصّص عند استدعائه.

navigation.addEventListener("navigate", event => {
  event.intercept({
    async handler() {
      doSyncStuff();
      await doAsyncStuff();
    }
  });
});

يعالج المتصفّح بالكامل عملية التنقّل، مثل الانتقال من أعلى الصفحة إلى عنصر ربط (يُعرَف ذلك بالانتقال من /a إلى /a#id)، حتى في التطبيقات المكوّنة من صفحة واحدة. ولكنّ الانتقال إلى عنصر ربط في "صفحة" أخرى (/a إلى /b#id)، وهو أمر بسيط في التطبيقات المكوّنة من صفحات متعددة، يكون أكثر تعقيدًا في التطبيقات المكوّنة من صفحة واحدة. على التطبيق اعتراض عملية الانتقال إلى /b#id باستخدام NavigateEvent.transitionWhile()، ثمّ استدعاء NavigateEvent.restoreScroll() لعرض العنصر الثابت. كما ذكرنا أعلاه، من الصعب حاليًا إجراء ذلك.

التغييرات التي أُجريت

في التطبيقات المكوّنة من صفحة واحدة، يمكنك الآن التحكّم في ما إذا كان المتصفّح سيتولى الانتقال إلى عنصر ربط أو ما إذا كان الرمز البرمجي سيتولى ذلك.

استخدام scroll()

سيحاول المتصفّح تلقائيًا معالجة الانتقال للأعلى أو للأسفل بعد تنفيذ معالج الاعتراض. إذا كنت تريد معالجة الانتقال للأعلى أو للأسفل بنفسك، اضبط scroll على "manual"، ثم استخدِم NavigateEvent.scroll() عندما يحاول المتصفّح ضبط موضع الانتقال للأعلى أو للأسفل.

navigation.addEventListener("manual", event => {
  scroll: "manual",
  event.intercept({
    async handler() {
      doSyncStuff();
      // Handle scrolling earlier than by default:
      event.scroll();
      await doAsyncStuff();
    }
  });
});

لا تزال طريقة restoreScroll() متاحة، ولكن تم إيقافها نهائيًا وستتم إزالتها في الإصدار 108 من Chrome.

الخاتمة

نأمل أن نُجري قريبًا تعديلات على مقالتنا حول Navigation API. في الوقت الحالي، تحتوي مواصفات واجهة برمجة التطبيقات هذه على الكثير من المعلومات المخصّصة لمطوّري الويب.

صورة Tim Gouw على Unsplash