39 KiB
بناء تطبيق مصرفي الجزء الأول: قوالب HTML والمسارات في تطبيق ويب
عندما قامت حاسوب التوجيه الخاص بـ Apollo 11 بالتنقل إلى القمر في عام 1969، كان عليه التبديل بين برامج مختلفة دون إعادة تشغيل النظام بالكامل. تعمل تطبيقات الويب الحديثة بطريقة مشابهة – فهي تغير ما تراه دون إعادة تحميل كل شيء من البداية. هذا يخلق تجربة سلسة وسريعة يتوقعها المستخدمون اليوم.
على عكس المواقع التقليدية التي تعيد تحميل الصفحات بالكامل لكل تفاعل، تقوم تطبيقات الويب الحديثة بتحديث الأجزاء التي تحتاج إلى تغيير فقط. هذا النهج، مثلما يقوم مركز التحكم بالتبديل بين شاشات مختلفة مع الحفاظ على الاتصال المستمر، يخلق تلك التجربة السلسة التي اعتدنا عليها.
إليك ما يجعل الفرق كبيرًا جدًا:
| التطبيقات التقليدية متعددة الصفحات | التطبيقات الحديثة ذات الصفحة الواحدة |
|---|---|
| التنقل | إعادة تحميل الصفحة بالكامل لكل شاشة |
| الأداء | أبطأ بسبب تنزيل HTML بالكامل |
| تجربة المستخدم | وميض الصفحات المزعج |
| مشاركة البيانات | صعوبة بين الصفحات |
| التطوير | ملفات HTML متعددة تحتاج إلى صيانة |
فهم التطور:
- التطبيقات التقليدية تتطلب طلبات من الخادم لكل عملية تنقل
- التطبيقات الحديثة ذات الصفحة الواحدة (SPAs) يتم تحميلها مرة واحدة وتحديث المحتوى ديناميكيًا باستخدام JavaScript
- توقعات المستخدمين الآن تفضل التفاعلات الفورية والسلسة
- فوائد الأداء تشمل تقليل استهلاك النطاق الترددي واستجابات أسرع
في هذا الدرس، سنقوم ببناء تطبيق مصرفي يحتوي على شاشات متعددة تتدفق معًا بسلاسة. مثلما يستخدم العلماء أدوات معيارية يمكن إعادة تكوينها لتجارب مختلفة، سنستخدم قوالب HTML كعناصر قابلة لإعادة الاستخدام يمكن عرضها حسب الحاجة.
ستعمل مع قوالب HTML (مخططات قابلة لإعادة الاستخدام لشاشات مختلفة)، توجيه JavaScript (النظام الذي يبدل بين الشاشات)، وواجهة برمجة التطبيقات الخاصة بتاريخ المتصفح (التي تحافظ على عمل زر الرجوع كما هو متوقع). هذه هي نفس التقنيات الأساسية التي تستخدمها أطر العمل مثل React، Vue، وAngular.
بحلول النهاية، سيكون لديك تطبيق مصرفي يعمل يوضح مبادئ التطبيقات ذات الصفحة الواحدة بشكل احترافي.
اختبار ما قبل المحاضرة
ما ستحتاجه
سنحتاج إلى خادم ويب محلي لاختبار تطبيقنا المصرفي – لا تقلق، الأمر أسهل مما يبدو! إذا لم يكن لديك واحد مثبت بالفعل، فقط قم بتثبيت Node.js وقم بتشغيل npx lite-server من مجلد المشروع الخاص بك. هذا الأمر المفيد يقوم بتشغيل خادم محلي ويفتح تطبيقك تلقائيًا في المتصفح.
التحضير
على جهاز الكمبيوتر الخاص بك، قم بإنشاء مجلد باسم bank مع ملف باسم index.html بداخله. سنبدأ من هذا القالب الأساسي:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Bank App</title>
</head>
<body>
<!-- This is where you'll work -->
</body>
</html>
إليك ما يوفره هذا القالب الأساسي:
- يحدد هيكل مستند HTML5 مع إعلان DOCTYPE الصحيح
- يهيئ ترميز الأحرف كـ UTF-8 لدعم النصوص الدولية
- يمكن التصميم المتجاوب باستخدام علامة meta الخاصة بالعرض لتوافق الأجهزة المحمولة
- يضع عنوانًا وصفيًا يظهر في علامة تبويب المتصفح
- ينشئ قسمًا نظيفًا للجسم حيث سنبني تطبيقنا
📁 معاينة هيكل المشروع
بحلول نهاية هذا الدرس، سيحتوي مشروعك على:
bank/ ├── index.html <!-- Main HTML with templates --> ├── app.js <!-- Routing and navigation logic --> └── style.css <!-- (Optional for future lessons) -->مسؤوليات الملفات:
- index.html: يحتوي على جميع القوالب ويوفر هيكل التطبيق
- app.js: يتعامل مع التوجيه، التنقل، وإدارة القوالب
- القوالب: تحدد واجهة المستخدم لتسجيل الدخول، لوحة التحكم، والشاشات الأخرى
قوالب HTML
تحل القوالب مشكلة أساسية في تطوير الويب. عندما اخترع غوتنبرغ الطباعة بالحروف المتحركة في الأربعينيات من القرن الخامس عشر، أدرك أنه بدلاً من نحت صفحات كاملة، يمكنه إنشاء كتل حروف قابلة لإعادة الاستخدام وترتيبها حسب الحاجة. تعمل قوالب HTML على نفس المبدأ – بدلاً من إنشاء ملفات HTML منفصلة لكل شاشة، تقوم بتحديد هياكل قابلة لإعادة الاستخدام يمكن عرضها عند الحاجة.
فكر في القوالب كمخططات لأجزاء مختلفة من تطبيقك. تمامًا كما يقوم المهندس المعماري بإنشاء مخطط واحد ويستخدمه عدة مرات بدلاً من إعادة رسم غرف متطابقة، نقوم بإنشاء القوالب مرة واحدة ونستخدمها حسب الحاجة. يحتفظ المتصفح بهذه القوالب مخفية حتى يقوم JavaScript بتنشيطها.
إذا كنت تريد إنشاء شاشات متعددة لصفحة ويب، فإن أحد الحلول هو إنشاء ملف HTML لكل شاشة تريد عرضها. ومع ذلك، يأتي هذا الحل مع بعض الإزعاج:
- يجب عليك إعادة تحميل HTML بالكامل عند تبديل الشاشة، مما قد يكون بطيئًا.
- من الصعب مشاركة البيانات بين الشاشات المختلفة.
نهج آخر هو أن يكون لديك ملف HTML واحد فقط، وتحديد قوالب HTML متعددة باستخدام عنصر <template>. القالب هو كتلة HTML قابلة لإعادة الاستخدام لا يتم عرضها بواسطة المتصفح، ويجب أن يتم إنشاؤها أثناء وقت التشغيل باستخدام JavaScript.
لنبدأ البناء
سنقوم بإنشاء تطبيق مصرفي يحتوي على شاشتين رئيسيتين: صفحة تسجيل الدخول ولوحة التحكم. أولاً، دعنا نضيف عنصرًا نائبًا إلى جسم HTML – هذا هو المكان الذي ستظهر فيه جميع شاشاتنا المختلفة:
<div id="app">Loading...</div>
فهم هذا العنصر النائب:
- ينشئ حاوية مع المعرف "app" حيث سيتم عرض جميع الشاشات
- يعرض رسالة تحميل حتى يقوم JavaScript بتهيئة الشاشة الأولى
- يوفر نقطة تركيب واحدة لمحتوانا الديناميكي
- يمكن استهدافه بسهولة من JavaScript باستخدام
document.getElementById()
💡 نصيحة احترافية: نظرًا لأن محتوى هذا العنصر سيتم استبداله، يمكننا وضع رسالة تحميل أو مؤشر سيتم عرضه أثناء تحميل التطبيق.
بعد ذلك، دعنا نضيف أسفل القالب HTML لصفحة تسجيل الدخول. في الوقت الحالي، سنضع فقط عنوانًا وقسمًا يحتوي على رابط سنستخدمه للتنقل.
<template id="login">
<h1>Bank App</h1>
<section>
<a href="/dashboard">Login</a>
</section>
</template>
تفصيل هذا القالب لتسجيل الدخول:
- يحدد قالبًا بمعرف فريد "login" لاستهدافه بواسطة JavaScript
- يتضمن عنوانًا رئيسيًا يحدد العلامة التجارية للتطبيق
- يحتوي على عنصر
<section>دلالي لتجميع المحتوى ذي الصلة - يوفر رابط تنقل ينقل المستخدمين إلى لوحة التحكم
ثم سنضيف قالب HTML آخر لصفحة لوحة التحكم. ستحتوي هذه الصفحة على أقسام مختلفة:
- رأس يحتوي على عنوان ورابط تسجيل الخروج
- الرصيد الحالي لحساب البنك
- قائمة المعاملات، معروضة في جدول
<template id="dashboard">
<header>
<h1>Bank App</h1>
<a href="/login">Logout</a>
</header>
<section>
Balance: 100$
</section>
<section>
<h2>Transactions</h2>
<table>
<thead>
<tr>
<th>Date</th>
<th>Object</th>
<th>Amount</th>
</tr>
</thead>
<tbody></tbody>
</table>
</section>
</template>
دعونا نفهم كل جزء من هذه اللوحة:
- يهيكل الصفحة باستخدام عنصر
<header>دلالي يحتوي على التنقل - يعرض عنوان التطبيق بشكل متسق عبر الشاشات للعلامة التجارية
- يوفر رابط تسجيل الخروج الذي يعيد المستخدم إلى شاشة تسجيل الدخول
- يعرض الرصيد الحالي للحساب في قسم مخصص
- ينظم بيانات المعاملات باستخدام جدول HTML منظم بشكل صحيح
- يحدد رؤوس الجدول لأعمدة التاريخ، الكائن، والمبلغ
- يترك جسم الجدول فارغًا لحقن المحتوى الديناميكي لاحقًا
💡 نصيحة احترافية: عند إنشاء قوالب HTML، إذا كنت تريد رؤية كيف ستبدو، يمكنك تعليق سطور
<template>و</template>عن طريق إحاطتها بـ<!-- -->.
✅ لماذا تعتقد أننا نستخدم سمات id على القوالب؟ هل يمكننا استخدام شيء آخر مثل الفئات؟
إحياء القوالب باستخدام JavaScript
الآن نحتاج إلى جعل قوالبنا وظيفية. مثلما تأخذ الطابعة ثلاثية الأبعاد مخططًا رقميًا وتخلق كائنًا ماديًا، يأخذ JavaScript قوالبنا المخفية ويخلق عناصر مرئية وتفاعلية يمكن للمستخدمين رؤيتها واستخدامها.
تتبع العملية ثلاث خطوات متسقة تشكل أساس تطوير الويب الحديث. بمجرد فهمك لهذا النمط، ستتعرف عليه عبر العديد من الأطر والمكتبات.
إذا جربت ملف HTML الحالي في المتصفح، سترى أنه يتوقف عند عرض Loading.... هذا لأننا بحاجة إلى إضافة بعض كود JavaScript لإنشاء وعرض قوالب HTML.
إنشاء قالب يتم عادةً في 3 خطوات:
- استرجاع عنصر القالب في DOM، على سبيل المثال باستخدام
document.getElementById. - نسخ عنصر القالب، باستخدام
cloneNode. - إرفاقه بـ DOM تحت عنصر مرئي، على سبيل المثال باستخدام
appendChild.
flowchart TD
A[🔍 Step 1: Find Template] --> B[📋 Step 2: Clone Template]
B --> C[🔗 Step 3: Attach to DOM]
A1["document.getElementById('login')"] --> A
B1["template.content.cloneNode(true)"] --> B
C1["app.appendChild(view)"] --> C
C --> D[👁️ Template Visible to User]
style A fill:#e1f5fe
style B fill:#f3e5f5
style C fill:#e8f5e8
style D fill:#fff3e0
تفصيل مرئي للعملية:
- الخطوة 1 تحدد موقع القالب المخفي في هيكل DOM
- الخطوة 2 تنشئ نسخة عمل يمكن تعديلها بأمان
- الخطوة 3 تدخل النسخة في منطقة الصفحة المرئية
- النتيجة هي شاشة وظيفية يمكن للمستخدمين التفاعل معها
✅ لماذا نحتاج إلى نسخ القالب قبل إرفاقه بـ DOM؟ ماذا تعتقد سيحدث إذا تخطينا هذه الخطوة؟
المهمة
قم بإنشاء ملف جديد باسم app.js في مجلد المشروع الخاص بك واستورد هذا الملف في قسم <head> من HTML:
<script src="app.js" defer></script>
فهم استيراد هذا السكربت:
- يربط ملف JavaScript بمستند HTML الخاص بنا
- يستخدم السمة
deferلضمان تشغيل السكربت بعد اكتمال تحليل HTML - يمكن الوصول إلى جميع عناصر DOM لأنها محملة بالكامل قبل تنفيذ السكربت
- يتبع أفضل الممارسات الحديثة لتحميل السكربت والأداء
الآن في app.js، سننشئ وظيفة جديدة باسم updateRoute:
function updateRoute(templateId) {
const template = document.getElementById(templateId);
const view = template.content.cloneNode(true);
const app = document.getElementById('app');
app.innerHTML = '';
app.appendChild(view);
}
خطوة بخطوة، إليك ما يحدث:
- يحدد عنصر القالب باستخدام معرفه الفريد
- ينشئ نسخة عميقة من محتوى القالب باستخدام
cloneNode(true) - يجد حاوية التطبيق حيث سيتم عرض المحتوى
- يمسح أي محتوى موجود من حاوية التطبيق
- يدخل محتوى القالب المنسوخ في DOM المرئي
الآن قم باستدعاء هذه الوظيفة مع أحد القوالب وانظر إلى النتيجة.
updateRoute('login');
ما يحققه استدعاء هذه الوظيفة:
- ينشط قالب تسجيل الدخول عن طريق تمرير معرفه كمعامل
- يوضح كيفية التبديل برمجيًا بين شاشات التطبيق المختلفة
- يعرض شاشة تسجيل الدخول بدلاً من رسالة "Loading..."
✅ ما هو الغرض من هذا الكود app.innerHTML = '';؟ ماذا يحدث بدونه؟
إنشاء المسارات
التوجيه يتعلق أساسًا بربط عناوين URL بالمحتوى الصحيح. فكر في كيفية استخدام مشغلي الهاتف الأوائل لوحات التبديل لتوصيل المكالمات – كانوا يأخذون طلبًا واردًا ويوجهونه إلى الوجهة الصحيحة. يعمل التوجيه في الويب بشكل مشابه، حيث يأخذ طلب عنوان URL ويحدد المحتوى الذي سيتم عرضه.
تقليديًا، كانت الخوادم تقوم بذلك عن طريق تقديم ملفات HTML مختلفة لعناوين URL مختلفة. بما أننا نبني تطبيقًا ذو صفحة واحدة، نحتاج إلى التعامل مع هذا التوجيه بأنفسنا باستخدام JavaScript. هذا النهج يمنحنا مزيدًا من التحكم في تجربة المستخدم والأداء.
flowchart LR
A["🌐 URL Path<br/>/dashboard"] --> B["🗺️ Routes Object<br/>Lookup"]
B --> C["🎯 Template ID<br/>'dashboard'"]
C --> D["📄 Find Template<br/>getElementById"]
D --> E["👁️ Display Screen<br/>Clone & Append"]
F["📍 /login"] --> G["🎯 'login'"]
H["📍 /unknown"] --> I["❌ Not Found"]
I --> J["🔄 Redirect to /login"]
style B fill:#e3f2fd
style E fill:#e8f5e8
style I fill:#ffebee
style J fill:#fff3e0
فهم تدفق التوجيه:
- تغييرات URL تؤدي إلى بحث في تكوين المسارات لدينا
- المسارات الصالحة ترتبط بمعرفات قوالب محددة للعرض
- المسارات غير الصالحة تؤدي إلى سلوك احتياطي لمنع الحالات المعطلة
- عرض القالب يتبع عملية الخطوات الثلاث التي تعلمناها سابقًا
عند الحديث عن تطبيق ويب، نسمي التوجيه النية لربط عناوين URL بشاشات محددة يجب عرضها. في موقع ويب يحتوي على ملفات HTML متعددة، يتم ذلك تلقائيًا حيث تنعكس مسارات الملفات على عنوان URL. على سبيل المثال، مع هذه الملفات في مجلد المشروع الخاص بك:
mywebsite/index.html
mywebsite/login.html
mywebsite/admin/index.html
إذا قمت بإنشاء خادم ويب مع mywebsite كالجذر، سيكون تعيين عنوان URL:
https://site.com --> mywebsite/index.html
https://site.com/login.html --> mywebsite/login.html
https://site.com/admin/ --> mywebsite/admin/index.html
ومع ذلك، بالنسبة لتطبيقنا، نحن نستخدم ملف HTML واحد يحتوي على جميع الشاشات لذا لن يساعدنا هذا السلوك الافتراضي. علينا إنشاء هذا التعيين يدويًا وتحديث القالب المعروض باستخدام JavaScript.
المهمة
سنستخدم كائنًا بسيطًا لتنفيذ خريطة بين مسارات URL وقوالبنا. أضف هذا الكائن في أعلى ملف app.js الخاص بك.
const routes = {
'/login': { templateId: 'login' },
'/dashboard': { templateId: 'dashboard' },
};
فهم تكوين المسارات هذا:
- يحدد تعيينًا بين مسارات URL ومعرفات القوالب
- يستخدم صياغة الكائن حيث تكون المفاتيح هي مسارات URL والقيم تحتوي على معلومات القالب
- يمكن البحث بسهولة عن القالب الذي سيتم عرضه لأي عنوان URL معين
- يوفر هيكلًا قابلًا للتوسع لإضافة مسارات جديدة في المستقبل
الآن دعنا نعدل قليلاً وظيفة updateRoute. بدلاً من تمرير معرف القالب مباشرة كمعامل، نريد استرجاعه من خلال النظر أولاً إلى عنوان URL الحالي، ثم استخدام خريطتنا للحصول على قيمة معرف القالب المقابلة. يمكننا استخدام window.location.pathname للحصول على قسم المسار فقط من عنوان URL.
function updateRoute() {
const path = window.location.pathname;
const route = routes[path];
const template = document.getElementById(route.templateId);
const view = template.content.cloneNode(true);
const app = document.getElementById('app');
app.innerHTML = '';
app.appendChild(view);
}
تفصيل ما يحدث هنا:
- يستخرج المسار الحالي من عنوان URL للمتصفح باستخدام
window.location.pathname - يبحث عن تكوين المسار المقابل في كائن المسارات الخاص بنا
- يسترجع معرف القالب من تكوين المسار
- يتبع نفس عملية عرض القالب كما كان من قبل
- ينشئ نظامًا ديناميكيًا يستجيب لتغييرات عنوان URL
هنا قمنا بتعيين المسارات التي أعلناها إلى القالب المقابل. يمكنك تجربتها للتأكد من أنها تعمل بشكل صحيح عن طريق تغيير عنوان URL يدويًا في المتصفح. ✅ ماذا يحدث إذا أدخلت مسارًا غير معروف في عنوان URL؟ كيف يمكننا حل هذه المشكلة؟
إضافة التنقل
مع إنشاء التوجيه، يحتاج المستخدمون إلى طريقة للتنقل عبر التطبيق. تقوم المواقع التقليدية بإعادة تحميل الصفحات بالكامل عند النقر على الروابط، لكننا نريد تحديث عنوان URL والمحتوى دون إعادة تحميل الصفحة. هذا يخلق تجربة أكثر سلاسة تشبه كيفية تبديل التطبيقات المكتبية بين وجهات النظر المختلفة.
نحتاج إلى تنسيق شيئين: تحديث عنوان URL في المتصفح حتى يتمكن المستخدمون من حفظ الصفحات ومشاركة الروابط، وعرض المحتوى المناسب. عند التنفيذ بشكل صحيح، يخلق هذا التنقل السلس الذي يتوقعه المستخدمون من التطبيقات الحديثة.
🏗️ نظرة معمارية: مكونات نظام التنقل
ما الذي تقوم ببنائه:
- 🔄 إدارة عنوان URL: تحديث شريط عنوان المتصفح دون إعادة تحميل الصفحات
- 📋 نظام القوالب: تبديل المحتوى ديناميكيًا بناءً على المسار الحالي
- 📚 تكامل التاريخ: الحفاظ على وظيفة أزرار الرجوع/التقدم في المتصفح
- 🛡️ معالجة الأخطاء: توفير حلول بديلة للمسارات غير الصالحة أو المفقودة
كيف تعمل المكونات معًا:
- الاستماع إلى أحداث التنقل (النقرات، تغييرات التاريخ)
- التحديث لعنوان URL باستخدام واجهة برمجة التطبيقات History API
- عرض القالب المناسب للمسار الجديد
- الحفاظ على تجربة مستخدم سلسة طوال الوقت
الخطوة التالية لتطبيقنا هي إضافة إمكانية التنقل بين الصفحات دون الحاجة إلى تغيير عنوان URL يدويًا. هذا يعني شيئين:
- تحديث عنوان URL الحالي
- تحديث القالب المعروض بناءً على عنوان URL الجديد
لقد قمنا بالفعل بمعالجة الجزء الثاني باستخدام وظيفة updateRoute، لذا علينا معرفة كيفية تحديث عنوان URL الحالي.
سنحتاج إلى استخدام JavaScript وبشكل أكثر تحديدًا history.pushState التي تسمح بتحديث عنوان URL وإنشاء إدخال جديد في سجل التصفح، دون إعادة تحميل HTML.
⚠️ ملاحظة مهمة: بينما يمكن استخدام عنصر HTML الرابط
<a href>بمفرده لإنشاء روابط إلى عناوين URL مختلفة، فإنه سيؤدي إلى إعادة تحميل HTML افتراضيًا. من الضروري منع هذا السلوك عند التعامل مع التوجيه باستخدام JavaScript مخصص، باستخدام وظيفة preventDefault() على حدث النقر.
المهمة
لنقم بإنشاء وظيفة جديدة يمكننا استخدامها للتنقل في تطبيقنا:
function navigate(path) {
window.history.pushState({}, path, path);
updateRoute();
}
فهم وظيفة التنقل هذه:
- تحديث عنوان URL للمتصفح إلى المسار الجديد باستخدام
history.pushState - إضافة إدخال جديد إلى سجل تاريخ المتصفح لدعم أزرار الرجوع/التقدم بشكل صحيح
- تشغيل وظيفة
updateRoute()لعرض القالب المقابل - الحفاظ على تجربة التطبيق أحادي الصفحة دون إعادة تحميل الصفحات
تقوم هذه الطريقة أولاً بتحديث عنوان URL الحالي بناءً على المسار المعطى، ثم تحديث القالب. الخاصية window.location.origin تُرجع جذر عنوان URL، مما يسمح لنا بإعادة بناء عنوان URL كامل من مسار معين.
الآن بعد أن لدينا هذه الوظيفة، يمكننا معالجة المشكلة التي لدينا إذا لم يتطابق المسار مع أي مسار محدد. سنقوم بتعديل وظيفة updateRoute بإضافة حل بديل إلى أحد المسارات الموجودة إذا لم نتمكن من العثور على تطابق.
function updateRoute() {
const path = window.location.pathname;
const route = routes[path];
if (!route) {
return navigate('/login');
}
const template = document.getElementById(route.templateId);
const view = template.content.cloneNode(true);
const app = document.getElementById('app');
app.innerHTML = '';
app.appendChild(view);
}
نقاط رئيسية يجب تذكرها:
- التحقق مما إذا كان هناك مسار موجود للمسار الحالي
- إعادة التوجيه إلى صفحة تسجيل الدخول عند الوصول إلى مسار غير صالح
- توفير آلية بديلة تمنع التنقل المعطل
- ضمان أن المستخدمين دائمًا يرون شاشة صالحة، حتى مع عناوين URL غير صحيحة
إذا لم يتم العثور على مسار، سنقوم الآن بإعادة التوجيه إلى صفحة login.
الآن لنقم بإنشاء وظيفة للحصول على عنوان URL عند النقر على رابط، ولمنع السلوك الافتراضي للرابط في المتصفح:
function onLinkClick(event) {
event.preventDefault();
navigate(event.target.href);
}
تفصيل معالج النقر هذا:
- منع السلوك الافتراضي للرابط في المتصفح باستخدام
preventDefault() - استخراج عنوان URL الوجهة من عنصر الرابط الذي تم النقر عليه
- استدعاء وظيفة التنقل المخصصة بدلاً من إعادة تحميل الصفحة
- الحفاظ على تجربة التطبيق أحادي الصفحة السلسة
<a href="/dashboard" onclick="onLinkClick(event)">Login</a>
...
<a href="/login" onclick="onLinkClick(event)">Logout</a>
ما الذي يحققه هذا الربط باستخدام onclick:
- ربط كل رابط بنظام التنقل المخصص لدينا
- تمرير حدث النقر إلى وظيفة
onLinkClickالخاصة بنا للمعالجة - تمكين التنقل السلس دون إعادة تحميل الصفحات
- الحفاظ على هيكل عنوان URL الصحيح الذي يمكن للمستخدمين حفظه أو مشاركته
تربط خاصية onclick حدث النقر بكود JavaScript، هنا استدعاء وظيفة navigate().
جرب النقر على هذه الروابط، يجب أن تكون الآن قادرًا على التنقل بين الشاشات المختلفة لتطبيقك.
✅ طريقة history.pushState هي جزء من معيار HTML5 ومُنفذة في جميع المتصفحات الحديثة. إذا كنت تقوم ببناء تطبيق ويب للمتصفحات القديمة، هناك حيلة يمكنك استخدامها بدلاً من هذه الواجهة البرمجية: باستخدام الهاش (#) قبل المسار يمكنك تنفيذ التوجيه الذي يعمل مع التنقل العادي للروابط ولا يعيد تحميل الصفحة، حيث كان الغرض منه إنشاء روابط داخلية داخل الصفحة.
جعل أزرار الرجوع والتقدم تعمل
تعتبر أزرار الرجوع والتقدم أساسية لتصفح الويب، تمامًا مثل كيفية مراجعة مراقبي مهام ناسا للحالات السابقة للنظام أثناء المهمات الفضائية. يتوقع المستخدمون أن تعمل هذه الأزرار، وعندما لا تعمل، فإنها تكسر تجربة التصفح المتوقعة.
يحتاج تطبيقنا أحادي الصفحة إلى تكوين إضافي لدعم ذلك. يحتفظ المتصفح بسجل تاريخ (الذي كنا نضيف إليه باستخدام history.pushState)، ولكن عندما يتنقل المستخدمون عبر هذا السجل، يحتاج تطبيقنا إلى الاستجابة عن طريق تحديث المحتوى المعروض وفقًا لذلك.
sequenceDiagram
participant User
participant Browser
participant App
participant Template
User->>Browser: Clicks "Login" link
Browser->>App: onclick event triggered
App->>App: preventDefault() & navigate('/dashboard')
App->>Browser: history.pushState('/dashboard')
Browser->>Browser: URL updates to /dashboard
App->>App: updateRoute() called
App->>Template: Find & clone dashboard template
Template->>App: Return cloned content
App->>Browser: Replace app content with template
Browser->>User: Display dashboard screen
Note over User,Template: User clicks browser back button
User->>Browser: Clicks back button
Browser->>Browser: History moves back to /login
Browser->>App: popstate event fired
App->>App: updateRoute() called automatically
App->>Template: Find & clone login template
Template->>App: Return cloned content
App->>Browser: Replace app content with template
Browser->>User: Display login screen
نقاط التفاعل الرئيسية:
- إجراءات المستخدم تُشغل التنقل من خلال النقرات أو أزرار المتصفح
- التطبيق يعترض النقرات على الروابط لمنع إعادة تحميل الصفحات
- واجهة برمجة التطبيقات History API تدير تغييرات عنوان URL وسجل تاريخ المتصفح
- القوالب توفر هيكل المحتوى لكل شاشة
- مستمعو الأحداث يضمنون استجابة التطبيق لجميع أنواع التنقل
استخدام history.pushState ينشئ إدخالات جديدة في سجل التنقل للمتصفح. يمكنك التحقق من ذلك عن طريق الضغط على زر الرجوع في متصفحك، يجب أن يعرض شيئًا مثل هذا:
إذا حاولت النقر على زر الرجوع عدة مرات، سترى أن عنوان URL الحالي يتغير ويتم تحديث السجل، لكن نفس القالب يستمر في العرض.
ذلك لأن التطبيق لا يعرف أننا بحاجة إلى استدعاء updateRoute() في كل مرة يتغير السجل. إذا نظرت إلى وثائق history.pushState، يمكنك أن ترى أنه إذا تغيرت الحالة - بمعنى أننا انتقلنا إلى عنوان URL مختلف - يتم تشغيل حدث popstate. سنستخدم ذلك لإصلاح هذه المشكلة.
المهمة
لضمان تحديث القالب المعروض عند تغيير سجل المتصفح، سنقوم بإرفاق وظيفة جديدة تستدعي updateRoute(). سنقوم بذلك في أسفل ملف app.js الخاص بنا:
window.onpopstate = () => updateRoute();
updateRoute();
فهم تكامل السجل هذا:
- الاستماع إلى أحداث
popstateالتي تحدث عندما يتنقل المستخدمون باستخدام أزرار المتصفح - استخدام وظيفة سهمية لتصريح مختصر لمعالج الحدث
- استدعاء
updateRoute()تلقائيًا كلما تغيرت حالة السجل - تهيئة التطبيق عن طريق استدعاء
updateRoute()عند تحميل الصفحة لأول مرة - ضمان عرض القالب الصحيح بغض النظر عن كيفية تنقل المستخدمين
💡 نصيحة احترافية: استخدمنا وظيفة سهمية هنا لتصريح معالج حدث
popstateالخاص بنا للاختصار، لكن وظيفة عادية ستعمل بنفس الطريقة.
إليك فيديو تذكيري عن وظائف السهم:
🎥 انقر على الصورة أعلاه لمشاهدة فيديو عن وظائف السهم.
الآن حاول استخدام أزرار الرجوع والتقدم في متصفحك، وتأكد من أن المسار المعروض يتم تحديثه بشكل صحيح هذه المرة.
تحدي وكيل GitHub Copilot 🚀
استخدم وضع الوكيل لإكمال التحدي التالي:
الوصف: قم بتحسين تطبيق البنك عن طريق تنفيذ معالجة الأخطاء وقالب صفحة 404 للمسارات غير الصالحة، مما يحسن تجربة المستخدم عند التنقل إلى صفحات غير موجودة.
المهمة: قم بإنشاء قالب HTML جديد مع معرف "not-found" يعرض صفحة خطأ 404 سهلة الاستخدام مع تصميم. ثم قم بتعديل منطق التوجيه في JavaScript لعرض هذا القالب عندما يتنقل المستخدمون إلى عناوين URL غير صالحة، وأضف زر "العودة إلى الصفحة الرئيسية" الذي يعيد التوجيه إلى صفحة تسجيل الدخول.
تعرف على المزيد حول وضع الوكيل هنا.
🚀 التحدي
أضف قالبًا ومسارًا جديدًا لصفحة ثالثة تعرض الاعتمادات لهذا التطبيق.
أهداف التحدي:
- إنشاء قالب HTML جديد مع هيكل محتوى مناسب
- إضافة المسار الجديد إلى كائن تكوين المسارات الخاص بك
- تضمين روابط التنقل إلى ومن صفحة الاعتمادات
- اختبار أن جميع التنقلات تعمل بشكل صحيح مع سجل المتصفح
اختبار ما بعد المحاضرة
المراجعة والدراسة الذاتية
التوجيه هو أحد الأجزاء التي تبدو معقدة في تطوير الويب، خاصة مع انتقال الويب من سلوكيات تحديث الصفحات إلى تحديثات تطبيقات الصفحة الواحدة. اقرأ قليلاً عن كيفية تعامل خدمة Azure Static Web App مع التوجيه. هل يمكنك شرح لماذا بعض القرارات الموضحة في تلك الوثيقة ضرورية؟
موارد تعليمية إضافية:
- استكشاف كيفية تنفيذ التوجيه على جانب العميل في أطر عمل شهيرة مثل React Router وVue Router
- البحث عن الفروقات بين التوجيه القائم على الهاش وتوجيه واجهة برمجة التطبيقات History API
- التعلم عن التقديم على جانب الخادم (SSR) وكيف يؤثر على استراتيجيات التوجيه
- التحقيق في كيفية تعامل تطبيقات الويب التقدمية (PWAs) مع التوجيه والتنقل
الواجب
إخلاء المسؤولية:
تم ترجمة هذا المستند باستخدام خدمة الترجمة بالذكاء الاصطناعي Co-op Translator. بينما نسعى لتحقيق الدقة، يرجى العلم أن الترجمات الآلية قد تحتوي على أخطاء أو عدم دقة. يجب اعتبار المستند الأصلي بلغته الأصلية المصدر الموثوق. للحصول على معلومات حاسمة، يُوصى بالترجمة البشرية الاحترافية. نحن غير مسؤولين عن أي سوء فهم أو تفسير خاطئ ينشأ عن استخدام هذه الترجمة.

