منابع آموزشی و پژوهشی، برای دانشگاه و مدرسه
پشتیبانیانتشار محتوا
مسیر یادگیری

جاوااسکریپت ۲؛ دورهٔ متوسط و پروژه‌های کاربردی

دورهٔ دوم و رایگان جاوااسکریپت، تألیف تحریریه درس‌آوند؛ ادامهٔ دورهٔ «جاوااسکریپت از صفر تا پروژه». ۲۴ درس سطح متوسط با مثال عملی، تمرین و پاسخ و سه پروژهٔ مدیریت هزینه، فروشگاه و API محلی تیکت. پیش‌نیاز: تسلط بر مبانی دورهٔ اول و HTML مقدماتی. زمان هر درس برآورد مطالعه و تمرین است؛ این نسخه ویدیو ندارد.

۲۴ درس۱٬۱۰۰ دقیقه۰ درس کامل‌شده
پرسش دربارهٔ این دوره
API تیکت، آزمون و کیفیت · درس ۲۳

۲۳. کیفیت رابط؛ فوکوس، فارسی‌سازی و اندازه‌گیری کارایی

دورهٔ رایگانثبت‌نام و پیشرفت یادگیری در حساب شما نگهداری می‌شود.ورود / ساخت حساب

کدی که فقط با ماوس روی رایانهٔ نویسنده کار می‌کند، تحویل کامل نیست. در این درس کیفیت را به رفتار قابل مشاهده تبدیل می‌کنیم: پس از حذف ردیف فوکوس کجاست، کاربر خطا را چگونه می‌فهمد، مبلغ چگونه نمایش داده می‌شود و کندی از کدام بخش می‌آید؟ هدف اضافه‌کردن تزیین نیست؛ می‌خواهیم سه پروژه در استفادهٔ واقعی قابل فهم‌تر و قابل بررسی‌تر باشند.

بازسازی DOM نباید محل کاربر را گم کند

در سبد همراه، renderCart ردیف‌ها را دوباره می‌سازد. دکمه‌ای که فعال شده ممکن است دیگر همان گره قبلی نباشد؛ بنابراین فوکوس را پس از رسم به دکمهٔ متناظر برمی‌گردانیم. اگر کاهش تعداد، ردیف آخر را حذف کرده باشد، عنوان سبد مقصد جایگزین است. عنوان در HTML با tabindex=-1 قابل فوکوس برنامه‌ای شده و وارد ترتیب عادی Tab نمی‌شود.

نمونهٔ زیر الگوی مستقلی است. تابع renderRows و ساختار داده در این مثال به پروژه اضافه نشده‌اند؛ مقصود، ترتیب ثبت مقصد و بازگرداندن فوکوس است. در فایل واقعی app.mjs همین تصمیم را در handler تعداد سبد پیدا کنید و با آن مقایسه کنید.

javascript
// فرض: این عناصر از قبل در صفحهٔ تمرین وجود دارند.
const host = document.querySelector('#cart');
const fallback = document.querySelector('#cart-heading');
function restoreCartFocus(id, delta) {
  const buttons = [...host.querySelectorAll('button[data-id][data-delta]')];
  const destination = buttons.find(button =>
    button.dataset.id === id && button.dataset.delta === String(delta)
  );
  (destination ?? fallback).focus();
}

قبل از فراخوانی، DOM تازه باید ساخته شده باشد. انتخاب با جست‌وجوی dataset در این نمونه از چسباندن شناسهٔ دلخواه به selector جلوگیری می‌کند. صرف focusکردن body مقصد مفیدی نیست. فوکوس را هم بعد از هر رندر بی‌دلیل جابه‌جا نکنید؛ کاربر هنگام تایپ جست‌وجو نباید ناگهان از input خارج شود. تصمیم به نوع تعامل وابسته است، نه فقط تابع render.

نمایش فارسی با دادهٔ محاسباتی فرق دارد

در مدل، مبلغ تومان عدد صحیح است. هنگام نمایش می‌توانیم رقم‌ها و جداکننده را محلی کنیم، اما مقدار فرمت‌شده را دوباره جمع نمی‌زنیم. این نمونه در Node.js یا مرورگر اجرا می‌شود؛ فاصله‌ها و جهت نمایش ممکن است با محیط متفاوت باشد، بنابراین آزمون مالی را روی عدد خام بنویسید.

javascript
const amount = 240000;
const formatter = new Intl.NumberFormat('fa-IR');
console.log(formatter.format(amount) + ' تومان');
console.log(amount + 10000); // 250000
const user = '<کاربر آزمایشی>';
const output = document.createElement('p'); // بخش مرورگری نمونه
output.textContent = user + '؛ مجموع: ' + formatter.format(amount);

در Node سه خط نخست را اجرا کنید؛ document فقط در مرورگر صفحه وجود دارد. تاریخ ورودی هزینه در این پروژه قالب استاندارد YYYY-MM-DD دارد و تقویم انتخابگر مرورگر ممکن است به زبان محیط وابسته باشد. نمایش فارسی تاریخ، به معنی تبدیل ذخیرهٔ استاندارد به رشتهٔ ظاهری نیست. قبل از افزودن تقویم جلالی، قرارداد تبدیل و روز نامعتبر را جدا آزمون کنید.

کندی را با یک پرسش مشخص بسنجید

برای کاتالوگ بزرگ می‌خواهیم بدانیم فیلتر و مرتب‌سازی چقدر هزینه دارد. نمونهٔ زیر را از یک فایل موقت در ریشهٔ بسته اجرا کنید. فقط مدل را اندازه می‌گیرد و شامل ساخت DOM، چیدمان و نقاشی صفحه نیست؛ این محدوده را در گزارش حفظ کنید.

javascript
import { searchProducts } from './projects/shop/model.mjs';
const rows = Array.from({ length: 1000 }, (_, i) => ({
  id: 'p-' + i, name: 'کتاب ' + i, category: 'کتاب', price: i, stock: 1
}));
performance.mark('filter-start');
for (let i = 0; i < 100; i++) {
  searchProducts(rows, { query: 'کتاب', sort: 'price' });
}
performance.mark('filter-end');
performance.measure('filter-100', 'filter-start', 'filter-end');
console.log(performance.getEntriesByName('filter-100')[0].duration);

یک عدد روی رایانهٔ شما معیار عمومی سرعت نیست. چند بار با داده و نسخهٔ یکسان اجرا و توزیع نتیجه را مقایسه کنید. اگر هدف بررسی تایپ جست‌وجوست، در DevTools ضبط Performance از همان تعامل بگیرید و ببینید زمان در JavaScript مصرف می‌شود یا رندر. افزودن debounce ممکن است تعداد اجرا را کم کند، اما تأخیر احساس‌شده هم می‌افزاید؛ بدون اندازه‌گیری، «بهینه‌تر» نامیدن آن دقیق نیست.

تمرین، پاسخ راهنما و معیار تحویل

بدون ماوس وارد فروشگاه شوید، محصول اضافه کنید، تعداد را کاهش دهید تا ردیف حذف شود و سپس با Tab ادامه دهید. مقصد باید قابل پیش‌بینی و فوکوس دیدنی باشد. در مرکز تیکت نیز خطای نسخه را ایجاد و بررسی کنید آیا متن پیام، قدم بعدی را روشن می‌کند. پیام فقط نباید با تغییر رنگ منتقل شود؛ متن خوانا لازم است.

برای بخش کارایی، نتیجهٔ اندازه‌گیری مدل را با ضبط تعامل صفحه مقایسه کنید. پاسخ راهنما: تفاوت ممکن است از ساخت صدها گره و محاسبهٔ چیدمان بیاید، پس تغییر الگوریتم فیلتر لزوماً کندی رابط را حل نمی‌کند. تحویل شامل شرح دستگاه و مرورگر، دادهٔ آزمون، مسیر صفحه‌کلید و یک تصمیم مبتنی بر اندازه‌گیری است. این تمرین دستی است؛ سبزبودن npm test به معنی عبور از آن نیست.

منابع رسمی برای مطالعهٔ بیشتر

https://web.dev/articles/using-tabindex
https://developer.mozilla.org/en-US/docs/Web/API/Performance/measure
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat

تألیف و مثال‌های اختصاصی: تحریریه درس‌آوند.

یکجا انتخاب کن، راحت‌تر دریافت کن

انتخاب‌های من ۰ منبع

مجموعهٔ مطالعه‌ات را بساز.

کنار مقاله‌ها «انتخاب» را بزنید تا چند فایل را با هم دریافت کنید.

انتخاب مقاله‌های رایگان