|
3 weeks ago | |
---|---|---|
.. | ||
README.md | 3 weeks ago | |
assignment.md | 4 weeks ago |
README.md
ساخت اپلیکیشن بانکی قسمت دوم: ساخت فرم ورود و ثبتنام
آزمون پیش از درس
مقدمه
در تقریباً تمام اپلیکیشنهای وب مدرن، شما میتوانید یک حساب کاربری ایجاد کنید تا فضای خصوصی خودتان را داشته باشید. از آنجا که چندین کاربر میتوانند به طور همزمان به یک اپلیکیشن وب دسترسی داشته باشند، نیاز به مکانیزمی دارید که دادههای شخصی هر کاربر را جداگانه ذخیره کند و مشخص کند کدام اطلاعات نمایش داده شود. ما نحوه مدیریت هویت کاربر به صورت امن را پوشش نمیدهیم، زیرا این موضوع به خودی خود گسترده است، اما مطمئن میشویم که هر کاربر بتواند یک (یا چند) حساب بانکی در اپلیکیشن ما ایجاد کند.
در این بخش، از فرمهای HTML برای اضافه کردن ورود و ثبتنام به اپلیکیشن وب خود استفاده خواهیم کرد. خواهیم دید که چگونه دادهها را به صورت برنامهریزی شده به یک API سرور ارسال کنیم و در نهایت چگونه قوانین اعتبارسنجی اولیه برای ورودیهای کاربر تعریف کنیم.
پیشنیاز
شما باید بخش قالبهای HTML و مسیریابی اپلیکیشن وب را برای این درس تکمیل کرده باشید. همچنین باید Node.js را نصب کرده و API سرور را به صورت محلی اجرا کنید تا بتوانید دادهها را برای ایجاد حسابها ارسال کنید.
توجه داشته باشید شما دو ترمینال به صورت همزمان اجرا خواهید کرد، همانطور که در زیر لیست شده است:
- برای اپلیکیشن بانکی اصلی که در درس قالبهای HTML و مسیریابی ساختیم
- برای API سرور اپلیکیشن بانکی که همین حالا تنظیم کردیم.
برای ادامه درس، باید هر دو سرور فعال باشند. این سرورها روی پورتهای مختلف (پورت 3000
و پورت 5000
) گوش میدهند، بنابراین همه چیز باید به خوبی کار کند.
میتوانید با اجرای این دستور در یک ترمینال، بررسی کنید که سرور به درستی اجرا شده است:
curl http://localhost:5000/api
# -> should return "Bank API v1.0.0" as a result
فرم و کنترلها
عنصر <form>
بخشی از یک سند HTML را محصور میکند که در آن کاربر میتواند دادهها را با کنترلهای تعاملی وارد و ارسال کند. انواع مختلفی از کنترلهای رابط کاربری (UI) وجود دارد که میتوان در یک فرم استفاده کرد، رایجترین آنها عناصر <input>
و <button>
هستند.
انواع مختلفی از ورودیها وجود دارد. به عنوان مثال، برای ایجاد یک فیلد که کاربر بتواند نام کاربری خود را وارد کند، میتوانید از این استفاده کنید:
<input id="username" name="username" type="text">
ویژگی name
به عنوان نام ویژگی زمانی که دادههای فرم ارسال میشوند استفاده خواهد شد. ویژگی id
برای مرتبط کردن یک <label>
با کنترل فرم استفاده میشود.
لیست کامل انواع
<input>
و سایر کنترلهای فرم را بررسی کنید تا ایدهای از تمام عناصر رابط کاربری بومی که میتوانید هنگام ساخت رابط کاربری خود استفاده کنید، به دست آورید.
✅ توجه داشته باشید که <input>
یک عنصر خالی است که نباید یک تگ بسته مطابقتدهنده به آن اضافه کنید. با این حال، میتوانید از نشانهگذاری خودبسته <input/>
استفاده کنید، اما این ضروری نیست.
عنصر <button>
در یک فرم کمی خاص است. اگر ویژگی type
آن را مشخص نکنید، به طور خودکار دادههای فرم را به سرور ارسال میکند. در اینجا مقادیر ممکن برای type
آورده شده است:
submit
: مقدار پیشفرض در یک<form>
، دکمه عمل ارسال فرم را اجرا میکند.reset
: دکمه تمام کنترلهای فرم را به مقادیر اولیه خود بازنشانی میکند.button
: هیچ رفتار پیشفرضی هنگام فشار دادن دکمه اختصاص نمیدهد. سپس میتوانید با استفاده از جاوااسکریپت اقدامات سفارشی به آن اختصاص دهید.
وظیفه
بیایید با اضافه کردن یک فرم به قالب 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) هستیم.
برای ارسال دادههای فرم به سرور بدون مجبور کردن بارگذاری مجدد صفحه، باید از کد جاوااسکریپت استفاده کنیم. به جای قرار دادن یک URL در ویژگی action
عنصر <form>
، میتوانید از هر کد جاوااسکریپت که با رشته 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 را مشاهده کنید.
ما از API 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 ترجمه شده است. در حالی که ما برای دقت تلاش میکنیم، لطفاً توجه داشته باشید که ترجمههای خودکار ممکن است شامل خطاها یا نادقتیهایی باشند. سند اصلی به زبان اصلی آن باید به عنوان منبع معتبر در نظر گرفته شود. برای اطلاعات حساس، ترجمه حرفهای انسانی توصیه میشود. ما هیچ مسئولیتی در قبال سوءتفاهمها یا تفسیرهای نادرست ناشی از استفاده از این ترجمه نداریم.