تاريخ النشر: 17 فبراير 2026
لقد اعتمدنا عليه لأكثر من عقد من الزمان window.history لإنشاء تطبيقات الصفحة الواحدة (SPA)، وقد اشتكينا من ذلك لأكثر من عقد من الزمان. السبب؟ لم يتم تصميمه أبدًا للمنتجعات الصحية. لتوفير تجربة سلسة، يجب على SPA تقليد التنقل القياسي متعدد الصفحات عن طريق النقر يدويًا على سجل المتصفح لدعم أزرار الرجوع والأمام.
خففت واجهة برمجة تطبيقات History من بعض نقاط الضعف هذه، ولكن ليس بدون عيوبها، مثل عدم القدرة على اكتشاف جميع أنواع مشغلات التنقل المختلفة. تشمل القيود الأخرى الملحوظة عدم القدرة على قراءة مكدس المحفوظات بالكامل، أو تحرير الإدخالات غير الحالية. ال popstate يتصرف الحدث أيضًا بشكل غير متسق، ولا يتم تشغيله متى pushState أو replaceState يتم استدعاؤها برمجيا.
تلك الحقبة تنتهي الآن. أصبحت واجهة برمجة تطبيقات التنقل موجودة، وأصبحت أخيرًا خطًا أساسيًا متاحًا حديثًا عبر جميع المتصفحات الرئيسية اعتبارًا من أوائل عام 2026.
مقارنة جنبا إلى جنب
لتوضيح الفرق، يقارن هذا القسم كيفية تعاملنا تاريخيًا مع التوجيه من جانب العميل مقابل الأسلوب الجديد والمبسط الذي تدعمه واجهة برمجة تطبيقات التنقل.
الطريقة القديمة
// 1. Function to navigate programmatically
function navigate(path)
// Update the URL without a page refresh
window.history.pushState( path , '', path);
// Manually trigger the UI update
renderContent(path);
// 2. Listener for browser navigation (Back/Forward buttons)
window.addEventListener('popstate', (event) => );
// 3. Mock UI renderer
function renderContent(path)
console.log(`Rendering UI for: $path...`);
// Example usage:
// navigate('/dashboard');
كيف تعمل واجهة برمجة تطبيقات التنقل
// 1. One central listener for ALL navigation
// This catches: links, back/forward buttons, AND programmatic calls
navigation.addEventListener('navigate', (event) =>
const url = new URL(event.destination.url);
// Intercept the navigation to prevent a full page reload
event.intercept(
async handler()
// The API handles the URL update; you just handle the UI
await renderContent(url.pathname);
);
);
// 2. Mock UI renderer
async function renderContent(path)
console.log(`Rendering UI for: $path...`);
// Example usage:
// navigation.navigate('/dashboard');
يبدو إنشاء جهاز توجيه باستخدام History API وكأنه تجميع للغز، حيث كان عليك القيام بما يلي:
- استمع للنقرات على
<a>العلامات على مستوى العالم. - يتصل
preventDefault()عليهم. - الاتصال يدويا
history.pushState(). - قم بتحديث DOM يدويًا.
- بشكل منفصل استمع ل
popstateحدث للتعامل مع أزرار الخلف/الأمام.
إذا نسيت التعامل مع حالة حافة واحدة، فقد ينتهي الأمر بالمستخدمين عن طريق الخطأ إلى عرض خاطئ، مما يسلط الضوء على هشاشتها.
تعمل واجهة برمجة تطبيقات التنقل على تبسيط هذا الأمر بشكل جذري. فهو يوفر لك NavigateEvent مركزيًا واحدًا لكل تنقل — سواء كان ذلك عندما ينقر المستخدم على رابط، أو يرسل نموذجًا، أو يضغط على زر الرجوع، أو يتصل بالرمز الخاص بك navigation.navigate().
ال event.intercept() تقوم الوظيفة بالكثير من المهام الثقيلة بالنسبة لك:
- تحديثات URL التلقائية: يعالج تحديث شريط العناوين ومكدس المحفوظات، دون الحاجة إلى الاتصال
pushState. - إمكانية الوصول التلقائي: يتعامل مع أساسيات إمكانية الوصول مثل إدارة التركيز (استعادة التركيز بعد التنقل) تلقائيًا.
- المنطق المركزي: يتعامل مع زر الرجوع والنقر فوق الأحداث في نفس الوظيفة بالضبط.
بعض حالات الاستخدام الأخرى
نحن نلقي نظرة على بعض الأمثلة الإضافية في هذا القسم لتسليط الضوء على المزيد من الطرق التي يمكن من خلالها الاستفادة من واجهة برمجة تطبيقات التنقل.
مثال: التعامل مع إرسال النموذج
يلتقط حدث التنقل تلقائيًا جميع عمليات إرسال نماذج المستند نفسه ويوفر خاصية NavigateEvent.formData للوصول إلى البيانات.
يلتقط هذا المثال إرسال نموذج HTML قياسي، ويمنع إعادة تحميل الصفحة، ويعالج البيانات بشكل غير متزامن.
// 1. One central listener handles links AND forms
navigation.addEventListener('navigate', (event) =>
// Only handle form POST submissions in this block
if (event.formData && event.canIntercept)
event.intercept(
async handler()
const data = event.formData;
console.log(`Submitting form data...`);
const username = data.get('username');
// Perform your async API call
postFormData(data);
// Update UI without a page refresh
renderSuccessMessage(username);
);
);
// 2. Standard HTML form (No JS 'onsubmit' needed!)
// <form action="/login" method="POST">
// <input name="username" type="text" required />
// <button type="submit">Login</button>
// </form>
مثال: التعامل مع التمرير غير المتزامن
في واجهة برمجة تطبيقات التنقل، event.scroll() يمنحك التحكم اليدوي في الوقت الذي يستعيد فيه المتصفح موضع التمرير أثناء التنقل.
افتراضيًا، يحاول المتصفح استعادة موضع التمرير مرة واحدة event.intercept() يسمى. ومع ذلك، في SPA الحديثة، غالبًا ما يكون المحتوى غير جاهز بعد (ربما تنتظر استجابة واجهة برمجة التطبيقات). إذا قام المتصفح بالتمرير قبل عرض المحتوى، فسوف يصل إلى المكان الخطأ أو سيبقى في الأعلى.
تخيل أن المستخدم ينقر على زر الرجوع للعودة إلى قائمة طويلة من العناصر. سنحتاج إلى جلب هذه العناصر قبل أن تصبح الصفحة طويلة بما يكفي للوصول إلى النهاية.
navigation.addEventListener('navigate', (event) =>
if (!event.canIntercept) return;
event.intercept(
// Tells the browser: "I will handle the scroll timing manually"
scroll: 'manual',
async handler()
// 1. Fetch data and render it
const data = await fetchListData();
renderItems(data);
// 2. Now that the items are in the DOM and the page has height,
// we can move the scrollbar to the saved position (for back/forward)
// or to the top (for new navigations).
event.scroll();
);
);
مثال: تمكين انتقالات العرض
تم تصميم واجهة برمجة تطبيقات التنقل وواجهة برمجة تطبيقات عرض الانتقالات للعمل معًا لإنشاء انتقالات سلسة “شبيهة بالتطبيق” في المنتجعات الصحية.
أثناء اعتراض حدث التنقل، يمكننا تغليف تحديثات DOM في document.startViewTransition(). هذا يخبر المتصفح بالتقاط لقطة للحالة “القديمة”، وإجراء تغييرات DOM المطلوبة، ثم تحريكها إلى الحالة “الجديدة”. وهذا يمكن أن يسمح لنا بدعم التحولات الشبيهة بالتطبيقات!
navigation.addEventListener('navigate', (event) =>
if (!event.canIntercept) return;
const url = new URL(event.destination.url);
event.intercept(
async handler()
// 1. Fetch the new content first (optional but recommended)
const content = await fetchNewPageContent(url.pathname);
// 2. Start the view transition
document.startViewTransition(() =>
// 3. Update the DOM inside the callback
// The browser snapshots the old UI before this and the new UI after
document.getElementById('app').innerHTML = content;
);
);
);
في ملخص
كما رأينا في الأمثلة السابقة، تعمل واجهة برمجة تطبيقات التنقل على إصلاح مشكلات معمارية عميقة أثناء التنقل في مناطق SPA، وهي نقطة معاناة طويلة الأمد بين العديد من مطوري الويب. إنه مدمج وآمن ويتعامل مع الحالات الطرفية بقوة.
اعتبارًا من أوائل عام 2026، ومع وصول الدعم إلى Safari وFirefox، أصبحت واجهة برمجة تطبيقات التنقل جاهزة للاستخدام في أوقات الذروة. إنه جهاز التوجيه الذي أردناه دائمًا — بسيط وقوي ومصمم للويب الحديث.