توسعه فرانت‌اند

وانیلا JavaScript: قدرت بدون فریمورک

چه زمانی بدون Framework کار کنیم؟ HTML پایه، رویداد، داده، امنیت و نگهداری را با فیلتر کامل فارسی در یک فایل HTML یاد بگیرید.

1405/01/04 2 دقیقه مطالعه 787 بازدید

برای ساختن یک فیلتر ساده یا فرم تعاملی، همیشه به Framework نیاز ندارید. Vanilla JavaScript نام کتابخانه خاصی نیست؛ اصطلاحی برای استفاده مستقیم از زبان و APIهای مرورگر است. این روش می‌تواند برای بخش کوچک یک صفحه، ابزار محدود یا یادگیری پایه مناسب باشد. اما «بدون Framework» به معنی بدون معماری، بدون وابستگی یا سریع‌ترین راه در همه پروژه‌ها نیست. مسئله اصلی اندازه و پیچیدگی رفتار، تجربه تیم و هزینه نگهداری است. باید بتوانید انتخاب خود را با نیاز واقعی توضیح دهید.

زبان و API مرورگر را جدا بشناسید

آرایه، تابع و Promise بخشی از JavaScript هستند؛ DOM، رویداد و Fetch از APIهای محیط مرورگرند. این تفاوت هنگام انتقال کد به محیط دیگر اهمیت دارد. تابعی که document می‌خواند، در هر Runtime قابل اجرا نیست. برای شروع، پایه زبان را با رفتار مرورگر ترکیب کنید ولی مرز را بشناسید. آموزش JavaScript در MDN مسیر مناسبی برای شناخت این رابطه و ساخت تعامل‌های اولیه ارائه می‌کند.

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

HTML پایه را سالم نگه دارید

قبل از افزودن کد، ساختار معنی‌دار بسازید. دکمه برای عمل و لینک برای مقصد استفاده شود. Label ورودی قابل مشاهده باشد و ترتیب صفحه‌کلید منطقی بماند. JavaScript نباید صرفاً برای جبران انتخاب عنصر نامناسب به کار برود. وقتی رفتار پایه با HTML درست ساخته شود، کد تعامل ساده‌تر و قابل فهم‌تر می‌شود. در طراحی فرم وب نیز ساختار و متن به اندازه منطق اجرا اهمیت دارند.

برای قابلیت افزوده، رفتار نبود JavaScript را مشخص کنید. بعضی صفحات می‌توانند محتوای کامل را نشان دهند و فقط ابزار فیلتر از کار بیفتد. بعضی ابزارها ذاتاً به کد نیاز دارند و باید این نیاز را روشن بگویند. Progressive Enhancement شعار عمومی نیست؛ باید معلوم باشد چه چیزی در مسیر پایه قابل استفاده است. اگر محتوا فقط پس از دریافت شبکه ساخته می‌شود، وضعیت انتظار و خطا هم بخشی از همین طراحی است.

نمونه کامل: جست‌وجوی فهرست راهنماها

نمونه زیر همه داده‌ها، HTML و JavaScript لازم را در یک فایل دارد. سه راهنمای فرضی از ابتدا در HTML وجود دارند. کد فقط آن‌ها را بر اساس عنوان فیلتر می‌کند و نتیجه را اعلام می‌کند. فایل را با نام index.html ذخیره و در مرورگر باز کنید؛ کتابخانه، API، سرور یا فایل دیگری لازم نیست. اگر JavaScript اجرا نشود، تمام موارد همچنان دیده می‌شوند و پیام پایه توضیح می‌دهد که فیلتر فعال نشده است.

<!doctype html>
<html lang="fa" dir="rtl"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>فیلتر راهنماها</title><style>body{font-family:system-ui;max-width:40rem;margin:2rem auto;padding:1rem;line-height:1.8}input,button{font:inherit;padding:.5rem}li{margin-block:.7rem}[hidden]{display:none!important}</style></head>
<body><main><h1>راهنماهای آموزشی فرضی</h1><label for="search">جست‌وجو در عنوان</label><input id="search" type="search" disabled><button id="clear" type="button" disabled>پاک کردن جست‌وجو</button><p id="status" role="status">فیلتر هنوز فعال نشده؛ همه راهنماها نمایش داده شده‌اند.</p><ul id="guides"><li>طراحی فرم وب</li><li>آشنایی با شبکه</li><li>مدیریت فایل پروژه</li></ul><p id="empty" hidden>عنوانی مطابق جست‌وجو پیدا نشد.</p></main>
<script>
const input=document.querySelector('#search');
const clear=document.querySelector('#clear');
const items=[...document.querySelectorAll('#guides li')];
const status=document.querySelector('#status');
const empty=document.querySelector('#empty');
const normalize=value=>value.trim().toLocaleLowerCase('fa').replaceAll('ي','ی').replaceAll('ك','ک');
function filter(){
 const query=normalize(input.value);
 let count=0;
 for(const item of items){const visible=normalize(item.textContent).includes(query);item.hidden=!visible;if(visible)count++;}
 status.textContent=`${count.toLocaleString('fa-IR')} راهنما نمایش داده می‌شود.`;
 empty.hidden=count!==0;
}
input.disabled=false;clear.disabled=false;
input.addEventListener('input',filter);
clear.addEventListener('click',()=>{input.value='';filter();input.focus();});
filter();
</script></body></html>

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

داده و نمایش در مثال

در این مثال، منبع داده همان عناصر فهرست‌اند و نیازی به نسخه جدا در آرایه نیست. هنگام شروع، ارجاع عناصر خوانده می‌شود. تابع filter نتیجه را بر اساس مقدار فعلی محاسبه می‌کند و hidden را تغییر می‌دهد. این انتخاب برای فهرست کوچک مناسب است. اگر داده از شبکه می‌آید یا فهرست پویا ساخته می‌شود، قرارداد متفاوتی لازم دارید. نباید نمونه کوچک را بدون بررسی به هزاران رکورد یا داده حساس تعمیم دهید.

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

Event Listener و چرخه عمر

رویداد input برای واکنش به تغییر مقدار استفاده شده است. رویداد click دکمه پاک کردن، مقدار را خالی و همان تابع فیلتر را اجرا می‌کند. تکرار منطق در چند Handler می‌تواند باعث اختلاف رفتار شود؛ تابع مشترک به حفظ قرارداد کمک می‌کند. در صفحه ساده، عناصر تا پایان عمر سند باقی‌اند. در رابطی که بخش‌ها مرتب ساخته و حذف می‌شوند، باید مدیریت Listenerها و منابع را هم در نظر بگیرید.

اضافه شدن مکرر Listener بدون پاک‌سازی یا قرارداد روشن ممکن است یک عمل را چند بار اجرا کند. Event Delegation در بعضی فهرست‌های پویا مفید است، اما همیشه لازم نیست. انتخاب روش باید به ساختار مربوط باشد. اگر State و DOM از هم جدا هستند، مشخص کنید کدام منبع معتبر است. تغییر دستی DOM در چند نقطه، بدون مدل روشن، به مرور فهم رفتار را سخت می‌کند؛ این یکی از جاهایی است که ابزار سازمان‌دهی می‌تواند ارزش پیدا کند.

امنیت داده بیرونی

متن کاربر یا سرویس بیرونی را بی‌بررسی به innerHTML ندهید. در مرجع textContent در MDN، نوشتن متن از تفسیر HTML جداست. این انتخاب برای نمایش متن معمولی مناسب است، اما همه مسائل امنیتی را حل نمی‌کند. URL، فایل و ساختارهای دیگر قرارداد و کنترل خود را دارند. اگر داده بیرونی دریافت می‌کنید، نوع و محدوده را در لایه مناسب بررسی کنید و Secret را در کد مرورگر قرار ندهید.

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

ماژول، ابزار ساخت و وابستگی

Vanilla JavaScript می‌تواند با ماژول و ابزار ساخت هم استفاده شود. «بدون Framework» الزاماً «بدون Build» نیست. برای فایل‌های ماژول، روش سرو کردن و مسیر وارد کردن باید درست باشد؛ اجرای مستقیم بعضی ساختارها از فایل محلی محدودیت دارد. اگر نمونه چندفایلی می‌دهید، همه فایل‌ها و دستور لازم را بیاورید. نمونه این مقاله یک فایل معمولی است تا این وابستگی اضافه نشود و خواننده بتواند رفتار اصلی را مستقل ببیند.

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

کارایی و دسترس‌پذیری

برای فهرست کوچک، فیلتر ساده هزینه قابل فهمی دارد. در داده بزرگ، تعداد عناصر و تغییر DOM می‌تواند مسئله شود. Debounce، بخش‌بندی یا پردازش سمت سرور را فقط با نیاز و رفتار مناسب انتخاب کنید. هر تأخیر در واکنش ورودی به معنی تجربه بهتر نیست. در Debounce و Throttle، این دو روش برای کنترل نرخ اجرا با کاربردهای متفاوت مطرح‌اند. ابزار را با نوع رویداد و انتظار کاربر هماهنگ کنید.

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

چه زمانی به Framework فکر کنیم؟

وقتی وضعیت مشترک، مسیرهای متعدد و تغییرهای پیچیده زیاد می‌شوند، قراردادهای Component و مدیریت State می‌توانند نگهداری را ساده‌تر کنند. این نقطه برای همه پروژه‌ها یکسان نیست. ابتدا مشکل را نام ببرید و سپس ابزار را ارزیابی کنید. در نقشه راه فرانت‌اند، فهم پایه به انتخاب آگاهانه ابزار کمک می‌کند. توان ساخت مثال کوچک بدون Framework، شما را از استفاده از Framework منع نمی‌کند؛ دلیل رفتار ابزار را روشن‌تر می‌سازد.

برای تحویل، منبع داده، رویدادها، روش اجرا و محدودیت را ثبت کنید. اگر کد فقط یک فیلتر محلی است، آن را موتور جست‌وجوی کامل معرفی نکنید. نمونه کامل و کوچک، خواننده را به فهم و تغییر دعوت می‌کند. قدرت Vanilla JavaScript در دسترسی مستقیم و گسترده به امکانات وب است؛ استفاده حرفه‌ای آن به معماری متناسب، امنیت و تجربه کاربر وابسته می‌ماند. انتخاب خوب آن است که مسئله را با هزینه قابل نگهداری حل کند.

واکنش به این مقاله

اشتراک‌گذاری این مقاله:
دیدگاه‌ها 0
۰ / ۲۰۰۰

هنوز دیدگاهی ثبت نشده

اولین نفری باشید که نظر می‌دهد!