جاوااسکریپت | JavaScript
492 subscribers
711 photos
160 videos
4 files
579 links
کانال @IR_javascript حاوی اطلاعات مفید در حوزه برنامه نویس فرانت که بصورت روزانه بروز می‌شود.
در این کانال شما به:
[1] مطالب تازه
[2] تحلیل‌های عمیق
[3] نکات آموزشی
[4] چالش
[5] ابزار و راهنمایی‌های کاربردی
دسترسی خواهید داشت.

🆔@IR_javascript
Download Telegram
واحد های اندازه گیری CSS (قسمت پنجم)

واحدهای نسبی جدید CSS: واحدهای کانتینری (Container Units) برای رابط‌های کاربری تطبیقی

در CSS به‌صورت سنتی برای پیاده‌سازی رابط‌های واکنش‌گرا از واحدهایی مانند vw و vh استفاده می‌شود. بااین‌حال، این واحدها در لِی‌اوت‌های پیچیده کارایی لازم را ندارند. مدیاکوئری‌ها، راه‌حل‌های موقتی و استفاده از درصدها تا حدی این مشکل را برطرف می‌کنند، اما با معرفی Container Queries و Container Units، بسیاری از این پیچیدگی‌ها عملاً به گذشته تعلق دارند.

واحدهای Container Units چیستند؟

‏Container Units واحدهای اندازه‌گیری‌ای هستند که بر اساس ابعاد یک کانتینر محاسبه می‌شوند؛ کانتینری که با استفاده از ویژگی container-type تعریف شده است. این رویکرد به ما اجازه می‌دهد تطبیق‌پذیری را با دقت و راحتی بسیار بیشتری پیاده‌سازی کنیم و به‌جای تکیه بر اندازه کل صفحه، ابعاد واقعی هر کامپوننت درون کانتینر خودش را در نظر بگیریم.

مهم‌ترین این واحدها عبارت‌اند از:

• cqw — معادل یک درصد از عرض کانتینر
• cqh — معادل یک درصد از ارتفاع کانتینر
• cqi — معادل یک درصد از اندازه inline کانتینر (وابسته به writing-mode)
• cqb — معادل یک درصد از اندازه block کانتینر
• cqmin و cqmax — به‌ترتیب حداقل و حداکثر ابعاد کانتینر

چرا این موضوع اهمیت دارد؟

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

• کاهش نیاز به مدیاکوئری‌ها
به‌جای نوشتن تعداد زیادی مدیاکوئری، می‌توان به‌سادگی از @container به‌همراه cqw استفاده کرد. این کار هم حجم کد را کمتر می‌کند و هم خوانایی آن را بهبود می‌بخشد.

• حذف بسیاری از هک‌های جاوااسکریپتی
دیگر نیازی نیست برای محاسبه ابعاد و تنظیم تایپوگرافی یا فاصله‌ها از ResizeObserver استفاده شود. اکنون می‌توان همه این کارها را مستقیماً با CSS انجام داد.

نکات مهم و ظریف

— کانتینر حتماً باید تعریف شود؛ برای مثال با container-type: inline-size.
— این واحدها فقط درون کانتینر عمل می‌کنند، بنابراین انتخاب نوع مناسب کانتینر اهمیت زیادی دارد.
— واحدهای cqi و cqb به‌ویژه زمانی بسیار مفید هستند که نیاز به پشتیبانی از writing-mode عمودی یا رابط‌های چندزبانه و بین‌المللی دارید.

چه زمانی باید از Container Units استفاده کرد؟

— در طراحی سیستم‌های طراحی (Design System) و کامپوننت‌های قابل استفاده مجدد.
— در لِی‌اوت‌های پیچیده مانند داشبوردها یا ویرایشگرها.
— در معماری‌های میکروفِرانت‌اند، جایی که کامپوننت‌ها باید کاملاً مستقل از یکدیگر باشند.

📝 مثال‌ها:

/* در این مثال، اندازه فونت .card__title به عرض کانتینر .card وابسته است، نه به عرض کل صفحه. */
.card {
container-type: inline-size;
}

.card__title {
font-size: 4cqw;
}

/* تایپوگرافی */
.title {
font-size: clamp(16px, 3cqw, 24px);
}

/* فاصله‌گذاری */
.card {
padding: 4cqi;
}


📌 تطبیق‌پذیری مبتنی بر viewport دیگر متعلق به دیروز است. Container Units گامی جدید به‌سوی تفکر کامپوننت‌محور در CSS محسوب می‌شوند. حالا کامپوننت‌های شما به صفحه وابسته نیستند و رفتاری قابل پیش‌بینی دارند؛ انگار CSS هوشمندتر شده، نه پیچیده‌تر.


#️⃣#tip #css
👥@IR_javascript_group
🆔@IR_javascript
👍21
چه زمانی باید اولویت بارگذاری را مشخص کنیم؟ 🤔

لود تنبل (‎loading="lazy"‎) بسیار کاربردی است: با به‌تعویق‌انداختن بارگذاری تصاویری که هنوز در دید کاربر نیستند، هم در مصرف ترافیک صرفه‌جویی می‌کند و هم سرعت بارگذاری صفحه را افزایش می‌دهد.

اما اگر برای تصاویر حیاتی اولویت مشخص نکنید، مرورگر خودش درباره ترتیب بارگذاری تصمیم می‌گیرد — و این تصمیم همیشه با اهداف شما هم‌راستا نیست. ☹️ در نتیجه ممکن است تصویر اصلی یا هدر دیرتر از حد لازم لود شود؛ این موضوع LCP را تضعیف می‌کند و حس «کند بودن» صفحه را به کاربر منتقل می‌کند. اگر ابعاد تصویر هم از قبل مشخص نشده باشند، حتی می‌تواند به CLS منجر شود.

🧩 چه کار باید کرد؟

✔️ برای تصاویر غیرحیاتی — با خیال راحت از ‎loading="lazy"‎ استفاده کنید. هم ترافیک را کاهش می‌دهد و هم به UX آسیبی نمی‌زند.

✔️ برای تصاویر حیاتی در اسکرین اول — فقط به ‎loading="lazy"‎ تکیه نکنید:
   یا ‎loading="lazy"‎ را حذف کنید،
   یا اولویت را صراحتاً مشخص کنید (‎fetchpriority="high"‎)،
   یا منبع را پیش‌بارگذاری کنید (‎<link rel="preload" as="image" href="…">‎).

✔️ همیشه ‎width‎ و ‎height‎ را مشخص کنید یا از ‎aspect-ratio‎ استفاده کنید — این کار جلوی CLS را می‌گیرد.

✔️ از ‎srcset‎ و ‎sizes‎ (و فرمت‌های مدرن مثل WebP و AVIF) استفاده کنید — تا مرورگر بتواند بهترین فایل را متناسب با دستگاه انتخاب کند.

✔️ LCP را در شرایط واقعی بررسی کنید — تست‌های لوکال همیشه رفتار واقعی در ذکر را بازتاب نمی‌دهند.

🧩 مثال:

<!-- تصویر مهم -->
<link rel="preload" as="image" href="/image.jpg">
<img src="/image.jpg" width="1200" height="600" fetchpriority="high" alt="...">

<!-- تصویر غیرحیاتی -->
<img src="/thumb.jpg" loading="lazy" width="400" height="300" alt="...">


🧩 چند اشتباه رایج:

⏺️ اعمال ‎loading="lazy"‎ روی همه تصاویر بدون استثنا — و از دست دادن کنترل روی LCP؛
⏺️ تکیه صرف بر ‎fetchpriority‎ و فراموش‌کردن ‎preload‎ و فرمت‌های تطبیقی؛
⏺️ پیش‌بارگذاری تعداد زیادی منبع — که می‌تواند کل فرایند بارگذاری را بدتر کند.

در نهایت، لود تنبل را باید به‌صورت گزینشی استفاده کرد. برای تصاویر اسکرین اول، اولویت را صریحاً مشخص کنید (با ‎preload‎ یا ‎fetchpriority‎) یا اصلاً آن‌ها را تنبل لود نکنید؛ برای بقیه تصاویر، با خیال راحت از لود تنبل استفاده کنید. به این شکل هم در مصرف ترافیک صرفه‌جویی می‌کنید و هم تجربه‌ای سریع و قابل‌پیش‌بینی به کاربر می‌دهید. 👍

#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
2👍1
پردازش ترکیب‌های کلیدی 🧑‍💻

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

کمی تئوری

✔️ ترکیب کلید در واقع یک رویداد واحد ‎keydown‎ است که داخل آن بررسی می‌کنیم:
  ⏺️ کدام کلید فشرده شده است؛
  ⏺️ آیا کلیدهای کمکی (Ctrl، Shift، Alt، Meta) نگه داشته شده‌اند یا نه؛

✔️ در مرورگر رویداد جداگانه‌ای با نام «Ctrl+S» وجود ندارد — همه‌چیز با شرط‌گذاری انجام می‌شود.

ویژگی‌های مهم رویداد

✔️ ‎event.key‎ — کاراکتر یا نام کلید (مثل "a" یا "Enter"
✔️ ‎event.code‎ — کلید فیزیکی روی کیبورد (مثل "KeyA" یا "Enter"
✔️ ‎event.ctrlKey‎، ‎event.shiftKey‎، ‎event.altKey‎، ‎event.metaKey‎ — کلیدهای کمکی.

مثال ساده: ‎Ctrl + S‎

document.addEventListener('keydown', (event) => {
if (event.ctrlKey && event.code === 'KeyS') {
event.preventDefault(); // در صورت نیاز، رفتار پیش‌فرض را لغو می‌کنیم
// منطق موردنظر ما
}
});


به چه نکاتی باید توجه کرد؟

هنگام تایپ در ‎input‎ و ‎textarea‎، هات‌کی‌ها را رهگیری نکنید؛
در macOS معمولاً به‌جای ‎Ctrl‎ از ‎Meta‎ (کلید Cmd) استفاده می‌شود؛
نگه‌داشتن یک کلید باعث تکرار چندباره رویداد ‎keydown‎ می‌شود؛
برای هات‌کی‌ها بهتر است از ‎event.code‎ استفاده کنید تا به چیدمان کیبورد وابسته نباشید.

و در نهایت، در استفاده از هات‌کی‌های سراسری زیاده‌روی نکنید — آن‌ها باید مکمل رابط کاربری باشند، نه جایگزین آن. 😁


#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
This media is not supported in your browser
VIEW IN TELEGRAM
ساده‌ترین روش برای غیرفعال کردن چندین عنصر فرم

می‌توانیم ویژگی «غیرفعال» را روی عنصر <fieldset> قرار دهیم تا به‌طور خودکار تمامی عناصر فرم تو در تو غیرفعال شوند.

#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
👍1
This media is not supported in your browser
VIEW IN TELEGRAM
تشخیص زمانی که کاربر بین تب‌های مرورگر جابه‌جا می‌شود و تغییر favicon

این ترفند را می‌توان با استفاده از Page Visibility API پیاده‌سازی کرد.

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

#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
This media is not supported in your browser
VIEW IN TELEGRAM
نود و نه درصد توسعه‌دهندگان از این ترفند در Chrome DevTools خبر ندارند 🤯

می‌توانید تم تاریک را روی هر سایتی فعال کنید، حتی اگر آن سایت خود تم تاریک نداشته باشد. برای این کار، DevTools را باز کرده، روی آیکون قلم‌مو کلیک کنید و گزینه‌ی Automatic Dark Mode را انتخاب نمایید.

این روش برای زمانی که در حال طراحی تم تاریک برای وب‌سایت خود هستید ایده‌آل است — شما فوراً پیش‌نمایشی از رابط کاربری تقریباً نود درصدی دریافت می‌کنید.

#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
3
This media is not supported in your browser
VIEW IN TELEGRAM
نکته‌ای درباره Chrome DevTools: بررسی سبک‌های placeholder

به‌طور پیش‌فرض، Chrome DevTools سبک‌های ::placeholder را هنگام بازرسی عناصر نمایش نمی‌دهد.

می‌توان با فعال کردن تنظیم Show user agent shadow DOM، shadow DOM مرورگر را که برای عناصر داخلی مختلف مانند <input>، <progress>، <video> و غیره ایجاد می‌شود، مشاهده کرد.

با بررسی این عناصر shadow DOM که توسط user agent ایجاد شده‌اند، می‌توان سبک‌های placeholder، نوار لغزنده‌ی ورودی‌های نوع range و موارد مشابه را مشاهده و ویرایش کرد.

#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
پژوهشگران ۳۷ هزار رزومهٔ جعلی از فارغ‌التحصیلان را ارسال کردند و بررسی کردند که چه کسانی بیشتر به مصاحبه دعوت می‌شوند [+لینک].

در این رزومه‌ها همه‌چیز به‌صورت تصادفی تغییر داده شده بود: رشتهٔ تحصیلی، دوره‌های کارآموزی، تحصیل در خارج از کشور و مهارت‌های کامپیوتری. نتایج جالبی که به‌طور غیرمنتظره جواب داد:

— کارآموزی‌هایی که بر توسعهٔ مهارت‌های نرم (Soft Skills) تمرکز دارند؛ آن هم حتی در درخواست برای موقعیت‌های شغلی تحلیلی(فقط بلد بودن کافی نیست شرکت‌ها به این هم توجه می‌کنند که آیا طرف «مهارت‌های انسانی» دارد یا نه) .

— تحصیل در خارج از کشور، همان‌طور که انتظار می‌رفت، شانس پیدا کردن سریع اولین شغل را افزایش می‌دهد.

— ترکیب برنامه‌نویسی + تحلیل داده‌ها یک امتیاز خیلی بزرگ برای دریافت تماس مجدد (دعوت به مصاحبه) ایجاد می‌کند. در حالی که هرکدام از این مهارت‌ها به‌تنهایی چنین اثری ندارند.

#️⃣#discussion
👥@IR_javascript_group
🆔@IR_javascript
ترجمهٔ روان به فارسی:

فرض کنید در CSS یک گرید ۵×۵ دارید. داخل این گرید عناصری با اندازه‌های مختلف قرار گرفته‌اند، اما به موقعیت‌های مشخصی ثابت نشده‌اند.

در چنین حالتی، استفاده از حالت `dense` برای ویژگی `grid-auto-flow` باعث می‌شود خانه‌های خالی‌ای که توسط عناصر قبلی ایجاد شده‌اند، پر شوند. به این شکل، عناصر بعدی که اندازه‌شان اجازه می‌دهد، به این فضاهای خالی منتقل می‌شوند.

این قابلیت مثلاً برای گالری تصاویر بسیار مفید است؛ جایی که عناصر (تصاویر) اندازه‌های تصادفی و متفاوتی دارند.

نمونه کد:

.grid {
grid-template-rows: repeat(5, 10rem);
grid-template-columns: repeat(5, 10rem);
}

.item-2 {
grid-row-end: span 2;
grid-column-end: span 2;
}


#️⃣#tip #css
👥@IR_javascript_group
🆔@IR_javascript
👏1
نکتهٔ CSS: سلکتور اتریبیوت بدون حساسیت به حروف بزرگ و کوچک

در CSS می‌توانیم با اضافه کردن حرف i به سلکتور اتریبیوت، کاری کنیم که انتخاب عناصر نسبت به حروف بزرگ و کوچک حساس نباشد.

یعنی فرقی نمی‌کند مقدار اتریبیوت با حروف بزرگ نوشته شده باشد یا کوچک؛ در هر صورت انتخاب می‌شود.

#️⃣#tip #css
👥@IR_javascript_group
🆔@IR_javascript
👍4
آیا می‌دانستید دکمهٔ ارسال فرم می‌تواند خارج از خود فرم قرار بگیرد؟

در بیشتر مواقع، دکمهٔ ارسال را داخل تگ <form> قرار می‌دهیم و این کار کاملاً درست است.
اما گاهی به‌دلیل محدودیت‌های چیدمان (layout) یا دلایل دیگر، منطقی‌تر است که دکمهٔ ارسال بیرون از تگ <form> قرار داده شود.

در این حالت می‌توانیم به‌سادگی با استفاده از ویژگی‌های form و id دکمه را به فرم موردنظر متصل کنیم.

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

#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
👍31👌1
این ۴ خط را به فایل `.vscode/settings.json` اضافه کنید تا تجربهٔ توسعه‌تان بلافاصله راحت‌تر و خواناتر شود.

با این تنظیمات، نام تب‌ها در VS Code واضح‌تر نمایش داده می‌شود (مثلاً مشخص می‌شود هر page یا layout مربوط به کدام پوشه است):

{
"workbench.editor.customLabels.patterns": {
"**/app/**/{page,layout,index}.{ts,tsx}": "(${dirname})/${filename}.${extname}",
"**/index.{ts,tsx}": "${dirname}/index.${extname}"
}
}


نتیجه:
وقتی چندین فایل page.tsx یا layout.tsx باز دارید، دیگر همه شبیه هم دیده نمی‌شوند و سریع‌تر متوجه می‌شوید هر فایل به کدام مسیر یا بخش پروژه تعلق دارد.


#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
غولِ دوست‌داشتنی ما: TypeScript به محبوب‌ترین زبان برنامه‌نویسی در GitHub تبدیل شد 🥳

و اگر JavaScript و TypeScript را با هم حساب کنیم، اختلاف با بقیه زبان‌ها واقعاً چشمگیر می‌شود.

گزارش کامل GitHub برای سال ۲۰۲۵:
https://github.blog/news-insights/octoverse/octoverse-a-new-developer-joins-github-every-second-as-ai-leads-typescript-to-1/

#️⃣#discussion
👥@IR_javascript_group
🆔@IR_javascript
2
‏در اینترنت به یک ابزار تحلیل CSS جالب برخوردم که می‌تواند هر وب‌سایتی را بررسی کند. این سرویس قادر است میزان و مقایسهٔ ویژگی اختصاصی‌بودن سلکتورها را محاسبه کند، پالت رنگی، سایه‌ها، حاشیه‌ها، متغیرهای CSS و چیدمان‌های گرید را نمایش دهد. حتی تلاش می‌کند پیشنهاد دهد که آیا مهاجرت به کلاس‌های اتمیک منطقی است یا خیر.

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

🔗https://cssstats.com/
#️⃣#tool
👥@IR_javascript_group
🆔@IR_javascript
1
فشرده‌سازی می‌تواند حجم فایل یک SVG را بدون کاهش کیفیت بصری آن کاهش دهد. برای این کار می‌توانید از ابزارهای آنلاین مختلفی مانند SVGOMG یا iLoveIMG استفاده کنید که فرایند فشرده‌سازی را ساده می‌کنند. کافی است فایل SVG خود را در این ابزارها بارگذاری کنید و تنظیمات فشرده‌سازی دلخواه را اعمال نمایید. سپس می‌توانید آن را به‌عنوان یک فایل جدید ذخیره و دانلود کنید. حتماً فایل را با نامی متفاوت ذخیره کنید تا نسخهٔ فشرده‌شده را از نسخهٔ اصلی تشخیص دهید (هرچند نسخهٔ فشرده‌شده باید حجم کمتری داشته باشد).


#️⃣#tool
👥@IR_javascript_group
🆔@IR_javascript
بدون ‎robots.txt‎ — بدون حضور در نتایج Google

موضوعی غیرمنتظره. Alan Smith یک مورد جالب را به اشتراک می‌گذارد: در مقطعی، ترافیک ارگانیک سایت از گوگل به صفر رسید. دلیل احتمالی این اتفاق آن بوده که سایت فاقد فایل ‎robots.txt‎ بوده است — فایلی در ریشهٔ سایت که باید به ربات‌ها اعلام کند کدام بخش‌ها قابل خزش هستند و کدام بخش‌ها نیستند.

بررسی‌های بعدی نشان داده که حتی در مستندات پشتیبانی نیز یک ویدیوی کامل دربارهٔ این نکته وجود دارد.

صادقانه بگویم، من هرگز با چنین موردی مواجه نشده‌ام، چون در همهٔ پروژه‌های شخصی‌ام فایل ‎robots.txt‎ به‌صورت خودکار از پروژهٔ قبلی کپی می‌شود. بااین‌حال، جالب است که اگر گوگل‌بات مجوز صریحی برای گشت‌وگذار در سایت دریافت نکند، خودسرانه عمل نمی‌کند و واقعاً وارد سایت نمی‌شود. منطقی است — اما در عین حال شگفت‌آور.

🔗https://www.alanwsmith.com/en/37/wa/jz/s1/
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
👍1
‌‎Data Loaders در Vue Router

دیتا لودرها کار با داده‌های ناهمگام (مثل واکشی API) را در Vue Router ساده و یکپارچه می‌کنند. با آن‌ها می‌توانید به شکل مؤثر داده‌ها را قبل از رندر کامپوننت آماده کنید و همزمان از کتابخانه‌هایی مثل Pinia Colada یا Apollo بهره ببرید.

// src/pages/users/[id].vue
<script lang="ts">
import { defineBasicLoader } from 'unplugin-vue-router/data-loaders/basic'
import { getUserById } from '../api'

export const useUserData = defineBasicLoader('/users/[id]', async (route) => {
return getUserById(route.params.id)
})
</script>


لودر به‌طور خودکار هنگام تغییر مسیر اجرا می‌شود و داده‌ها قبل از رندر کامپوننت آماده هستند. همچنین می‌توانید همان لودر را در چند کامپوننت دوباره استفاده کنید و داده‌ها به‌صورت اشتراکی مدیریت شوند.

🔗https://uvr.esm.is/data-loaders/
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
🧐 چرا نباید منطق کسب‌وکار را در کامپوننت‌های UI نوشت

اغلب یک الگوی تکراری را می‌بینم: یک کامپوننت کوچک با چند شرط ساده که پس از چند قابلیت کوچک به موجودی عظیم تبدیل می‌شود 🤯 — هم رابط را نمایش می‌دهد، هم تصمیم می‌گیرد، هم با API ارتباط برقرار می‌کند و کمی «جادو» هم انجام می‌دهد. در نتیجه، به‌جای یک UI تمیز، مجموعه‌ای از منطق پنهان خواهیم داشت که نگهداری آن بعداً بسیار دشوار است.

---

🧩 چگونه این اتفاق می‌افتد؟

در ابتدا همه چیز منطقی به نظر می‌رسد: زمان‌بندی محدود، فیتچر کوچک — ساده‌تر است که پردازش را مستقیم در کامپوننت قرار دهیم. سپس «بعداً بیرون می‌کشیم» هیچ‌گاه اتفاق نمی‌افتد و کامپوننت رشد می‌کند:

فراخوانی API و تبدیل پاسخ‌ها
تصمیم‌گیری درباره گام‌های فرایند
شامل شاخه‌های قوانین کسب‌وکار
منبعی برای کپی‌پیست هنگام استفاده مجدد

---

🧩 مشکل چیست؟

☑️ ادغام نقش‌ها — کامپوننت باید رابط را نمایش دهد، نه مدیریت فرایند را. وقتی UI شروع به «تفکر» می‌کند، سیستم بسیار شکننده می‌شود.
☑️ از بین رفتن قابلیت استفاده مجدد — نیاز به همان منطق در جای دیگر باعث کپی‌پیست، ناهماهنگی و باگ‌ها می‌شود.
☑️ ریسک تغییرات — تغییر نمایش، فرایند را خراب می‌کند؛ تغییر قانون، UI را به‌طور غیرمنتظره می‌شکند.
☑️ پیچیدگی تست

---

🧩 چرا با این حال منطق را در کامپوننت‌ها می‌نویسند؟

⏺️ سریع‌تر در شروع پروژه
⏺️ «برای یک قابلیت کوچک» به‌نظر می‌رسد نیازی به جداکردن نیست
⏺️ تیم خسته است یا استاندارد معماری وجود ندارد

اما معمولاً همان «قابلیت کوچک» رشد می‌کند و بدهی فنی انباشته می‌شود 😥

---

🧩 چگونه بهتر کد را سازمان‌دهی کنیم؟

✔️ کامپوننت‌های UI — مسئول نمایش و واکنش به تعاملات کاربر
✔️ منطق کسب‌وکار — در سرویس‌ها، استورها یا ماژول‌ها
✔️ یکپارچه‌سازی — کامپوننت‌ها سرویس‌ها یا اکشن‌ها را فراخوانی کرده و داده‌ها/وضعیت‌های آماده را دریافت می‌کنند

مثال جریان داده:
کامپوننت → اکشن / use-case → سرویس → مخزن/API → سرویس → use-case → کامپوننت (وضعیت به‌روز شده)

---

🧩 چگونه خود را بررسی کنیم؟

اگر قالب (template) را از کامپوننت حذف کنیم و کد باقی‌مانده هنوز معنای مستقلی داشته باشد — یعنی منطق کسب‌وکار به کامپوننت نفوذ کرده است. این نشانه‌ای برای تفکر درباره ریفکتورینگ است.

💡 نتیجه‌گیری:
UI = لایه نمایش
منطق کسب‌وکار = لایه تصمیم‌گیری

ادغام آن‌ها ممکن است در ابتدا راحت باشد، اما در بلندمدت تقریباً همیشه منجر به افزایش پیچیدگی، شکنندگی سیستم و بدهی فنی می‌شود 🙈


#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
3👍1
خاص‌بودگی در CSS (معادل Specificity) به معنای «وزن» یا «قدرت» یک سلکتور است.
هرچه خاص‌بودگی یک سلکتور بیشتر باشد، در صورت تعارض با سایر قوانین، احتمال برنده شدن آن بیشتر است.
به‌صورت خلاصه، ترتیب قدرت به این شکل است:
استایل درون‌خطی > شناسه (ID) > کلاس و شبه‌کلاس > عناصر و شبه‌عناصر
خاص‌بودگی معمولاً به شکل یک چهار‌تایی نمایش داده می‌شود، مانند:
(صفر، صفر، صفر، یک)
این اعداد به‌ترتیب نشان‌دهندهٔ تعداد استایل‌های درون‌خطی، شناسه‌ها، کلاس‌ها/شبه‌کلاس‌ها و عناصر هستند.
بنابراین «خاص‌بودگی» یعنی میزان اولویت یک قانون CSS هنگام بروز تداخل.
#myId#myId#myId span {
/* 0-3-0-1 */
}
.myClass.myClass.myClass span {
/* 0-0-3-1 */
}



#️⃣#tip #css
👥@IR_javascript_group
🆔@IR_javascript