24 KiB
بناء تطبيق مصرفي الجزء 2: إنشاء نموذج تسجيل دخول وتسجيل حساب
اختبار ما قبل المحاضرة
المقدمة
في معظم تطبيقات الويب الحديثة، يمكنك إنشاء حساب للحصول على مساحة خاصة بك. نظرًا لأن العديد من المستخدمين يمكنهم الوصول إلى تطبيق ويب في نفس الوقت، تحتاج إلى آلية لتخزين بيانات كل مستخدم بشكل منفصل وتحديد المعلومات التي سيتم عرضها. لن نتناول كيفية إدارة هوية المستخدم بشكل آمن لأنها موضوع واسع بحد ذاته، ولكننا سنتأكد من أن كل مستخدم يمكنه إنشاء حساب بنكي واحد (أو أكثر) في تطبيقنا.
في هذا الجزء، سنستخدم نماذج HTML لإضافة تسجيل الدخول والتسجيل إلى تطبيق الويب الخاص بنا. سنرى كيفية إرسال البيانات إلى واجهة برمجة التطبيقات الخاصة بالخادم برمجيًا، وأخيرًا كيفية تحديد قواعد التحقق الأساسية لإدخالات المستخدم.
المتطلبات الأساسية
يجب أن تكون قد أكملت قوالب HTML والتوجيه لتطبيق الويب لهذه الدرسة. كما تحتاج إلى تثبيت Node.js وتشغيل واجهة برمجة التطبيقات للخادم محليًا حتى تتمكن من إرسال البيانات لإنشاء الحسابات.
ملاحظة مهمة
ستحتاج إلى تشغيل نافذتي طرفية في نفس الوقت كما هو موضح أدناه:
- لتطبيق البنك الرئيسي الذي قمنا ببنائه في درس قوالب HTML والتوجيه.
- لواجهة برمجة التطبيقات الخاصة بتطبيق البنك Bank APP server API التي قمنا بإعدادها أعلاه.
يجب أن يكون كلا الخادمين قيد التشغيل لمتابعة بقية الدرس. يتم الاستماع على منافذ مختلفة (المنفذ 3000
والمنفذ 5000
) لذا يجب أن يعمل كل شيء بشكل جيد.
يمكنك اختبار أن الخادم يعمل بشكل صحيح عن طريق تنفيذ هذا الأمر في نافذة طرفية:
curl http://localhost:5000/api
# -> should return "Bank API v1.0.0" as a result
النماذج وعناصر التحكم
عنصر <form>
يضم قسمًا من مستند HTML حيث يمكن للمستخدم إدخال البيانات وإرسالها باستخدام عناصر تحكم تفاعلية. هناك جميع أنواع عناصر واجهة المستخدم (UI) التي يمكن استخدامها داخل النموذج، وأكثرها شيوعًا هي عناصر <input>
و<button>
.
هناك العديد من الأنواع المختلفة لعناصر <input>
، على سبيل المثال لإنشاء حقل حيث يمكن للمستخدم إدخال اسم المستخدم الخاص به يمكنك استخدام:
<input id="username" name="username" type="text">
سيتم استخدام خاصية name
كاسم الخاصية عند إرسال بيانات النموذج. يتم استخدام خاصية id
لربط <label>
بعنصر التحكم في النموذج.
ألقِ نظرة على القائمة الكاملة لأنواع
<input>
وعناصر التحكم الأخرى في النماذج للحصول على فكرة عن جميع عناصر واجهة المستخدم الأصلية التي يمكنك استخدامها عند بناء واجهتك.
✅ لاحظ أن <input>
هو عنصر فارغ لا يجب أن تضيف له علامة إغلاق مطابقة. يمكنك مع ذلك استخدام صيغة الإغلاق الذاتي <input/>
، لكنها ليست مطلوبة.
عنصر <button>
داخل النموذج له سلوك خاص. إذا لم تحدد خاصية type
، فسيقوم تلقائيًا بإرسال بيانات النموذج إلى الخادم عند الضغط عليه. فيما يلي القيم الممكنة لخاصية type
:
submit
: القيمة الافتراضية داخل<form>
، الزر يقوم بتشغيل إجراء إرسال النموذج.reset
: الزر يعيد جميع عناصر التحكم في النموذج إلى قيمها الأولية.button
: لا يتم تعيين سلوك افتراضي عند الضغط على الزر. يمكنك بعد ذلك تعيين إجراءات مخصصة له باستخدام JavaScript.
المهمة
لنبدأ بإضافة نموذج إلى قالب login
. سنحتاج إلى حقل اسم المستخدم وزر تسجيل الدخول.
<template id="login">
<h1>Bank App</h1>
<section>
<h2>Login</h2>
<form id="loginForm">
<label for="username">Username</label>
<input id="username" name="user" type="text">
<button>Login</button>
</form>
</section>
</template>
إذا نظرت عن كثب، يمكنك ملاحظة أننا أضفنا أيضًا عنصر <label>
هنا. يتم استخدام عناصر <label>
لإضافة اسم لعناصر واجهة المستخدم، مثل حقل اسم المستخدم الخاص بنا. التسميات مهمة لقراءة النماذج، ولكنها تأتي أيضًا بفوائد إضافية:
- من خلال ربط التسمية بعنصر التحكم في النموذج، فإنها تساعد المستخدمين الذين يستخدمون تقنيات المساعدة (مثل قارئ الشاشة) على فهم البيانات المطلوبة.
- يمكنك النقر على التسمية لوضع التركيز مباشرة على عنصر الإدخال المرتبط، مما يجعل الوصول إليه أسهل على الأجهزة التي تعمل باللمس.
إمكانية الوصول على الويب موضوع مهم غالبًا ما يتم تجاهله. بفضل عناصر HTML الدلالية ليس من الصعب إنشاء محتوى يمكن الوصول إليه إذا استخدمتها بشكل صحيح. يمكنك قراءة المزيد عن إمكانية الوصول لتجنب الأخطاء الشائعة وتصبح مطورًا مسؤولًا.
الآن سنضيف نموذجًا ثانيًا للتسجيل، أسفل النموذج السابق مباشرة:
<hr/>
<h2>Register</h2>
<form id="registerForm">
<label for="user">Username</label>
<input id="user" name="user" type="text">
<label for="currency">Currency</label>
<input id="currency" name="currency" type="text" value="$">
<label for="description">Description</label>
<input id="description" name="description" type="text">
<label for="balance">Current balance</label>
<input id="balance" name="balance" type="number" value="0">
<button>Register</button>
</form>
باستخدام خاصية value
يمكننا تحديد قيمة افتراضية لحقل معين.
لاحظ أيضًا أن الإدخال الخاص بـ balance
له النوع number
. هل يبدو مختلفًا عن الحقول الأخرى؟ حاول التفاعل معه.
✅ هل يمكنك التنقل والتفاعل مع النماذج باستخدام لوحة المفاتيح فقط؟ كيف يمكنك القيام بذلك؟
إرسال البيانات إلى الخادم
الآن بعد أن أصبح لدينا واجهة مستخدم وظيفية، الخطوة التالية هي إرسال البيانات إلى الخادم. دعنا نجري اختبارًا سريعًا باستخدام الكود الحالي: ماذا يحدث إذا نقرت على زر تسجيل الدخول أو التسجيل؟
هل لاحظت التغيير في قسم عنوان URL في المتصفح؟
الإجراء الافتراضي لـ <form>
هو إرسال النموذج إلى عنوان URL الحالي للخادم باستخدام طريقة GET، مع إلحاق بيانات النموذج مباشرة بعنوان URL. ومع ذلك، لهذه الطريقة بعض العيوب:
- البيانات المرسلة محدودة الحجم (حوالي 2000 حرف).
- البيانات مرئية مباشرة في عنوان URL (وهذا ليس جيدًا لكلمات المرور).
- لا تعمل مع تحميل الملفات.
لهذا السبب يمكنك تغييرها لاستخدام طريقة POST التي ترسل بيانات النموذج إلى الخادم في جسم طلب HTTP، دون أي من القيود السابقة.
بينما تُعد POST الطريقة الأكثر استخدامًا لإرسال البيانات، في بعض السيناريوهات المحددة يُفضل استخدام طريقة GET، مثل عند تنفيذ حقل بحث.
المهمة
أضف خصائص action
وmethod
إلى نموذج التسجيل:
<form id="registerForm" action="//localhost:5000/api/accounts" method="POST">
الآن حاول تسجيل حساب جديد باستخدام اسمك. بعد النقر على زر التسجيل، يجب أن ترى شيئًا مثل هذا:
إذا سار كل شيء على ما يرام، يجب أن يجيب الخادم على طلبك باستجابة JSON تحتوي على بيانات الحساب التي تم إنشاؤها.
✅ حاول التسجيل مرة أخرى بنفس الاسم. ماذا يحدث؟
إرسال البيانات دون إعادة تحميل الصفحة
كما لاحظت على الأرجح، هناك مشكلة بسيطة في النهج الذي استخدمناه للتو: عند إرسال النموذج، نخرج من تطبيقنا ويعيد المتصفح التوجيه إلى عنوان URL الخاص بالخادم. نحن نحاول تجنب جميع عمليات إعادة تحميل الصفحات مع تطبيق الويب الخاص بنا، حيث نقوم بإنشاء تطبيق صفحة واحدة (SPA).
لإرسال بيانات النموذج إلى الخادم دون إجبار إعادة تحميل الصفحة، علينا استخدام كود JavaScript. بدلاً من وضع عنوان URL في خاصية action
لعنصر <form>
، يمكنك استخدام أي كود JavaScript مسبوقًا بالسلسلة javascript:
لتنفيذ إجراء مخصص. باستخدام هذا، يعني أنك ستحتاج إلى تنفيذ بعض المهام التي كانت تتم تلقائيًا بواسطة المتصفح:
- استرداد بيانات النموذج.
- تحويل وترميز بيانات النموذج إلى تنسيق مناسب.
- إنشاء طلب HTTP وإرساله إلى الخادم.
المهمة
استبدل خاصية action
لنموذج التسجيل بـ:
<form id="registerForm" action="javascript:register()">
افتح app.js
وأضف وظيفة جديدة باسم register
:
function register() {
const registerForm = document.getElementById('registerForm');
const formData = new FormData(registerForm);
const data = Object.fromEntries(formData);
const jsonData = JSON.stringify(data);
}
هنا نسترد عنصر النموذج باستخدام getElementById()
ونستخدم مساعد FormData
لاستخراج القيم من عناصر التحكم في النموذج كمجموعة من أزواج المفتاح/القيمة. ثم نحول البيانات إلى كائن عادي باستخدام Object.fromEntries()
وأخيرًا نقوم بتسلسل البيانات إلى JSON، وهو تنسيق شائع الاستخدام لتبادل البيانات على الويب.
البيانات الآن جاهزة للإرسال إلى الخادم. قم بإنشاء وظيفة جديدة باسم createAccount
:
async function createAccount(account) {
try {
const response = await fetch('//localhost:5000/api/accounts', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: account
});
return await response.json();
} catch (error) {
return { error: error.message || 'Unknown error' };
}
}
ماذا تفعل هذه الوظيفة؟ أولاً، لاحظ الكلمة المفتاحية async
هنا. هذا يعني أن الوظيفة تحتوي على كود سيتم تنفيذه بشكل غير متزامن. عند استخدامها مع الكلمة المفتاحية await
، فإنها تسمح بالانتظار حتى يتم تنفيذ الكود غير المتزامن - مثل انتظار استجابة الخادم هنا - قبل المتابعة.
إليك فيديو سريع عن استخدام async/await
:
🎥 انقر على الصورة أعلاه لمشاهدة فيديو عن async/await.
نستخدم واجهة fetch()
لإرسال بيانات JSON إلى الخادم. تأخذ هذه الطريقة معلمين:
- عنوان URL الخاص بالخادم، لذا نضع هنا
//localhost:5000/api/accounts
. - إعدادات الطلب. هنا نحدد الطريقة بـ
POST
ونوفرbody
للطلب. بما أننا نرسل بيانات JSON إلى الخادم، نحتاج أيضًا إلى تعيين رأسContent-Type
إلىapplication/json
حتى يعرف الخادم كيفية تفسير المحتوى.
بما أن الخادم سيرد على الطلب بـ JSON، يمكننا استخدام await response.json()
لتحليل محتوى JSON وإرجاع الكائن الناتج. لاحظ أن هذه الطريقة غير متزامنة، لذا نستخدم الكلمة المفتاحية await
هنا قبل الإرجاع للتأكد من أن أي أخطاء أثناء التحليل يتم التقاطها أيضًا.
الآن أضف بعض الكود إلى وظيفة register
لاستدعاء createAccount()
:
const result = await createAccount(jsonData);
بما أننا نستخدم الكلمة المفتاحية await
هنا، نحتاج إلى إضافة الكلمة المفتاحية async
قبل وظيفة register:
async function register() {
أخيرًا، دعنا نضيف بعض السجلات للتحقق من النتيجة. يجب أن تبدو الوظيفة النهائية كما يلي:
async function register() {
const registerForm = document.getElementById('registerForm');
const formData = new FormData(registerForm);
const jsonData = JSON.stringify(Object.fromEntries(formData));
const result = await createAccount(jsonData);
if (result.error) {
return console.log('An error occurred:', result.error);
}
console.log('Account created!', result);
}
كان ذلك طويلاً بعض الشيء ولكننا وصلنا! إذا فتحت أدوات المطور في المتصفح، وحاولت تسجيل حساب جديد، يجب ألا ترى أي تغيير في صفحة الويب ولكن ستظهر رسالة في وحدة التحكم تؤكد أن كل شيء يعمل.
✅ هل تعتقد أن البيانات يتم إرسالها إلى الخادم بشكل آمن؟ ماذا لو تمكن شخص ما من اعتراض الطلب؟ يمكنك قراءة المزيد عن HTTPS لمعرفة المزيد عن الاتصال الآمن للبيانات.
التحقق من البيانات
إذا حاولت تسجيل حساب جديد دون إدخال اسم مستخدم أولاً، يمكنك أن ترى أن الخادم يعيد خطأ برمز الحالة 400 (طلب غير صالح).
قبل إرسال البيانات إلى الخادم، من الجيد التحقق من بيانات النموذج مسبقًا عند الإمكان، للتأكد من أنك ترسل طلبًا صالحًا. توفر عناصر التحكم في النماذج في HTML5 التحقق المدمج باستخدام سمات مختلفة:
required
: يجب ملء الحقل وإلا لا يمكن إرسال النموذج.minlength
وmaxlength
: تحدد الحد الأدنى والأقصى لعدد الأحرف في الحقول النصية.min
وmax
: تحدد الحد الأدنى والأقصى لقيمة الحقل الرقمي.type
: تحدد نوع البيانات المتوقعة، مثلnumber
،email
،file
أو أنواع أخرى مدمجة. قد يغير هذا السمة أيضًا العرض المرئي لعنصر التحكم في النموذج.pattern
: يسمح بتحديد نمط تعبير منتظم لاختبار ما إذا كانت البيانات المدخلة صالحة أم لا. يمكنك تخصيص مظهر عناصر التحكم في النموذج الخاص بك بناءً على كونها صحيحة أو غير صحيحة باستخدام الفئات الزائفة CSS:valid
و:invalid
.
المهمة
هناك حقلان مطلوبان لإنشاء حساب جديد صالح، وهما اسم المستخدم والعملة، بينما تكون الحقول الأخرى اختيارية. قم بتحديث كود HTML الخاص بالنموذج، باستخدام كل من السمة required
والنص في تسمية الحقل بحيث:
<label for="user">Username (required)</label>
<input id="user" name="user" type="text" required>
...
<label for="currency">Currency (required)</label>
<input id="currency" name="currency" type="text" value="$" required>
على الرغم من أن تنفيذ الخادم الحالي لا يفرض حدودًا محددة على الحد الأقصى لطول الحقول، إلا أنه من الجيد دائمًا تحديد حدود معقولة لأي إدخال نصي من المستخدم.
أضف سمة maxlength
إلى حقول النص:
<input id="user" name="user" type="text" maxlength="20" required>
...
<input id="currency" name="currency" type="text" value="$" maxlength="5" required>
...
<input id="description" name="description" type="text" maxlength="100">
الآن إذا قمت بالضغط على زر تسجيل ولم يحترم أحد الحقول قاعدة التحقق التي قمنا بتعريفها، سترى شيئًا مثل هذا:
التحقق الذي يتم تنفيذه قبل إرسال أي بيانات إلى الخادم يسمى التحقق من جانب العميل. ولكن لاحظ أنه ليس من الممكن دائمًا إجراء جميع الفحوصات دون إرسال البيانات. على سبيل المثال، لا يمكننا التحقق هنا مما إذا كان الحساب موجودًا بالفعل بنفس اسم المستخدم دون إرسال طلب إلى الخادم. التحقق الإضافي الذي يتم على الخادم يسمى التحقق من جانب الخادم.
عادةً ما يتم تنفيذ كلا النوعين، وبينما يحسن التحقق من جانب العميل تجربة المستخدم من خلال تقديم ملاحظات فورية، فإن التحقق من جانب الخادم ضروري لضمان أن البيانات التي تتعامل معها آمنة وسليمة.
🚀 التحدي
اعرض رسالة خطأ في HTML إذا كان المستخدم موجودًا بالفعل.
إليك مثال على الشكل الذي يمكن أن تبدو عليه صفحة تسجيل الدخول النهائية بعد إضافة بعض التنسيقات:
اختبار ما بعد المحاضرة
المراجعة والدراسة الذاتية
أصبح المطورون مبدعين للغاية في جهودهم لبناء النماذج، خاصة فيما يتعلق باستراتيجيات التحقق. تعرف على تدفقات النماذج المختلفة من خلال تصفح CodePen؛ هل يمكنك العثور على نماذج مثيرة وملهمة؟
الواجب
قم بتنسيق تطبيق البنك الخاص بك
إخلاء المسؤولية:
تم ترجمة هذا المستند باستخدام خدمة الترجمة بالذكاء الاصطناعي Co-op Translator. بينما نسعى لتحقيق الدقة، يرجى العلم أن الترجمات الآلية قد تحتوي على أخطاء أو معلومات غير دقيقة. يجب اعتبار المستند الأصلي بلغته الأصلية المصدر الموثوق. للحصول على معلومات حاسمة، يُوصى بالاستعانة بترجمة بشرية احترافية. نحن غير مسؤولين عن أي سوء فهم أو تفسيرات خاطئة ناتجة عن استخدام هذه الترجمة.