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

🆔@IR_javascript
Download Telegram
در این مطلب می‌خواهیم درباره دو هوک کاربردی در Vue به نام‌های onRenderTracked() و onRenderTriggered() صحبت کنیم — ابزارهایی که معمولاً کمتر مورد استفاده قرار می‌گیرند، در حالی که بسیار مفید هستند!

### این دو چه کاری انجام می‌دهند؟

‏- `onRenderTracked`: نشان می‌دهد که Vue هنگام رندر شدن، چه چیزهایی را دنبال و رصد می‌کند (یعنی چه چیزی را "ردگیری" می‌کند).
‏- `onRenderTriggered`: مشخص می‌کند که چه چیزی تغییر کرده و باعث اجرای مجدد رندر شده است.

### چه زمانی باید از آن‌ها استفاده کرد؟

- زمانی که یک کامپوننت بیش از حد و بدون دلیل واضحی رندر می‌شود.
- وقتی قصد بهینه‌سازی عملکرد (Performance Debugging) را دارید.
- زمانی که مشغول بررسی کدی هستید که توسط فرد دیگری نوشته شده یا خودتان مدتی پیش نوشته‌اید و حالا علت رفتارهای آن را نمی‌دانید.

### نمونه‌ای از استفاده:

<script setup>
import { ref, onRenderTracked, onRenderTriggered } from 'vue';

const count = ref(۰);
const name = ref('Vue');

onRenderTracked((e) => {
console.log('[tracked]', e);
});

onRenderTriggered((e) => {
console.log('[triggered]', e);
});
</script>

<template>
<div>
<p>شمارنده: {{ count }}</p>
<p>نام: {{ name }}</p>
<button @click="count++">افزایش</button>
</div>
</template>


زمانی که روی دکمه کلیک می‌کنید، در کنسول پیغامی مشابه زیر نمایش داده می‌شود:

[triggered] { target: ..., key: "count", type: "set" }


### چه چیزی در این هوک‌ها به شما داده می‌شود؟

Vue یک شیء با فیلدهای زیر به شما تحویل می‌دهد:

‏- effect: ارجاع به افکت واکنشی (یعنی رندر مربوطه)
‏- target: شیئی که تحت نظر قرار گرفته یا باعث اجرای مجدد شده (مانند ref یا reactive)
‏- key: فیلد مشخصی که رصد شده (مثل count یا name)
‏- type: نوع عملیات (مانند get`، `set`، `add`، `delete`، `clear)
‏- oldValue و newValue (در onRenderTriggered) — مقادیر پیش و پس از تغییر

### چه کاربردهای مفیدی دارند؟

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

#### لاگ‌گیری وابستگی‌ها
می‌توانید اطلاعات ردیابی‌شده را در قالب جدول چاپ کنید تا راحت‌تر متوجه شوید کامپوننت شما چه چیزهایی را دنبال می‌کند:

onRenderTracked((e) => {
console.table({
key: e.key,
type: e.type,
target: e.target
});
});


#### تحلیل عملکرد
می‌توانید شمارنده‌ای برای تعداد دفعات اجرای onRenderTriggered قرار دهید. اگر با یک کلیک، ده‌ها بار این تابع اجرا شود، احتمال وجود یک مشکل در ساختار کامپوننت وجود دارد.

---

### خلاصه:
‏- onRenderTracked = ببین Vue هنگام رندر چه چیزی را ردیابی می‌کند.
‏- onRenderTriggered = ببین چه چیزی تغییر کرده و باعث رندر مجدد شده.
- این ابزارها برای دیباگ و بهینه‌سازی بسیار کاربردی هستند.
- فقط در حالت توسعه (dev mode) استفاده شوند.



#️⃣#tip #vue
👥@IR_javascript_group
🆔@IR_javascript
👍3
کامپوننت KeepAlive در Vue یک کامپوننت پوششی خاص است که اجازه می‌دهد یک کامپوننت پس از حذف شدن از DOM همچنان در حافظه باقی بماند. به‌عبارت دیگر، Vue آن را از بین نمی‌برد، بلکه به‌آرامی کنار می‌گذارد تا در صورت نیاز دوباره مورد استفاده قرار گیرد. عملکرد آن شبیه به display: none است، با این تفاوت که تمام داده‌ها، واکنش‌پذیری و وضعیت داخلی کامپوننت حفظ می‌شود.

### کاربرد رایج:
فرض کنید در برنامه خود از زبانه‌ها (Tabs) یا مسیرها (Routes) استفاده می‌کنید و می‌خواهید هنگام جابه‌جایی بین زبانه‌ها، اطلاعات واردشده، موقعیت اسکرول و سایر وضعیت‌ها حفظ شوند:

<KeepAlive>
<component :is="currentTabComponent" />
</KeepAlive>


### اگر بخواهم کنترل کنم چه چیزی کش شود، چه کنم؟

از نسخه دو ممیز یک ممیز صفر به بعد، KeepAlive دارای دو پراپرتی include و exclude است که می‌توانید نام کامپوننت‌ها را برای کش شدن یا نشدن، در آن‌ها مشخص کنید.

#### نمونه‌ها:

رشته‌ای از نام‌ها (با ویرگول جدا شده):

<KeepAlive include="a,b">
<component :is="view" />
</KeepAlive>


عبارت منظم (Regex):

<KeepAlive :include="/a|b/">
<component :is="view" />
</KeepAlive>


آرایه‌ای از نام‌ها:

<KeepAlive :include="['a', 'b']">
<component :is="view" />
</KeepAlive>


### همچنین می‌توانید از prop به نام max استفاده کنید تا مشخص کنید حداکثر چند کامپوننت در حافظه نگهداری شود:

<KeepAlive max="۲">
<component :is="currentTabComponent" />
</KeepAlive>


---

### چه چیزهایی در Vue ۳ جدید است؟

در گذشته، یک کامپوننت یا کش می‌شد یا نمی‌شد — همین! اما در Vue ۳، امکانات بیشتری برای کنترل رفتار فراهم شده است.

### رفتار جدید: هوک‌های onActivated و onDeactivated

وقتی یک کامپوننت در KeepAlive قرار می‌گیرد، برخلاف حالت عادی، Vue دیگر unmounted را اجرا نمی‌کند. در عوض، این دو هوک اجرا می‌شوند:

onActivated(() => {
console.log('من دوباره فعال شدم!');
});

onDeactivated(() => {
console.log('وقت استراحته!');
});


این یعنی شما می‌توانید:
- تایمرها را موقتاً متوقف کنید
- از منابع سنگین جدا شوید (unsubscribe)
- انیمیشن‌ها را متوقف کرده یا به حالت تعلیق درآورید

### چه زمانی بهتر است استفاده نشود؟

- زمانی که کامپوننت "ارزان" است و رندر شدن آن زمان زیادی نمی‌برد
- زمانی که حفظ وضعیت کامپوننت برایتان اهمیتی ندارد
- زمانی که می‌خواهید کامپوننت با هر بار نمایش، کاملاً از نو ساخته شود

---

### خلاصه‌ی مطالب:

‏- KeepAlive کامپوننت‌ها را در حافظه نگه می‌دارد
- از onActivated و onDeactivated به‌جای unmounted استفاده می‌کند
- امکان فیلتر کردن کامپوننت‌ها با include و exclude وجود دارد
- می‌توان با max تعداد کامپوننت‌های ذخیره‌شده را محدود کرد
- فقط با یک فرزند (یا تگ <component>) به‌درستی کار می‌کند



#️⃣#tip #vue
👥@IR_javascript_group
🆔@IR_javascript
2
گاهی اوقات هنگام نوشتن یک کامپوننت، انواع ویژگی‌ها مانند id`، `class`، `style و یا ویژگی‌هایی با پیشوند data-* را به آن ارسال می‌کنید، اما این ویژگی‌ها در خروجی نهایی ناپدید می‌شوند. چرا؟ چون Vue به‌صورت پیش‌فرض این ویژگی‌ها را به‌طور خودکار روی تمام المنت‌ها اعمال نمی‌کند. ولی موضوع به همین سادگی هم نیست — ظرافت‌هایی دارد.

### دقیقاً چه اتفاقی می‌افتد؟

Vue تمامی ویژگی‌هایی را که صراحتاً به‌عنوان props تعریف نکرده‌اید**، جمع‌آوری کرده و آن‌ها را روی **المان ریشه‌ای (Root Element) کامپوننت شما قرار می‌دهد.

#### مثال:
<MyButton class="big red" id="super-btn" />


و درون MyButton.vue چنین چیزی نوشته‌اید:

<template>
<button>کلیک کن</button>
</template>


در این صورت، ویژگی‌های class="big red" و id="super-btn" به دکمه اضافه می‌شوند.
ساده و کاربردی، نه؟

---

### اگر از ساختار سفارشی استفاده کرده باشم چه می‌شود؟

اگر نخواهید Vue به‌طور خودکار این ویژگی‌ها را به هر جایی منتقل کند و ترجیح دهید خودتان تعیین کنید این ویژگی‌ها به کدام عنصر بروند**، در این صورت می‌توانید از `v-bind="$attrs"` استفاده کنید.

#### نمونه:

<template>
<div>
<button>دکمه شماره یک</button>
<button v-bind="$attrs">دکمه شماره دو</button>
</div>
</template>



در اینجا فقط دکمه دوم ویژگی‌هایی مثل `id` و `class` را دریافت می‌کند.

---

### اگر اصلاً نخواهید Vue چیزی منتقل کند چه؟

اگر بخواهید کنترل کامل را در دست داشته باشید، می‌توانید انتقال خودکار ویژگی‌ها را غیرفعال کنید. کافی‌ست گزینه زیر را در کامپوننت‌تان اضافه کنید:


<template>
<div class="wrapper">
<button v-bind="$attrs">دکمه</button>
</div>
</template>

<script setup>
defineOptions({
inheritAttrs: false
})
</script>



در این حالت، **هیچ ویژگی‌ای به عنصر ریشه‌ای (div) اضافه نمی‌شود
و تنها به دکمه منتقل خواهد شد. این کار زمانی بسیار مفید است که بخواهید استایل‌ها یا رویدادها دقیقاً روی یک عنصر تعاملی مثل دکمه اعمال شوند.

---

### نکات مهم:

- هر چیزی که prop نباشد، در $attrs قرار می‌گیرد.
- به‌صورت پیش‌فرض، تمام این ویژگی‌ها به عنصر ریشه‌ای کامپوننت افزوده می‌شوند.
- اگر می‌خواهید کنترل بیشتری داشته باشید، از inheritAttrs: false و v-bind="$attrs" استفاده کنید.
- می‌توان $attrs را هم در بخش setup و هم در template به‌کار برد.
- اگر نام یک ویژگی با نام prop یکی باشد، آن ویژگی دیگر وارد $attrs نمی‌شود.

این ویژگی‌ها به شما کمک می‌کنند کنترل دقیق‌تری بر ساختار، استایل و رفتار کامپوننت‌های خود داشته باشید — خصوصاً در کامپوننت‌های قابل استفاده مجدد و پیچیده.

#️⃣#tip #vue
👥@IR_javascript_group
🆔@IR_javascript
👍2
برخی وب‌سایت‌ها وجود دارند که امکان باز کردن ابزارهای توسعه‌دهنده مرورگر (DevTools) در آن‌ها فراهم نیست. این محدودیت‌ها به روش‌های خاصی اعمال می‌شوند:

### جلوگیری از نمایش منو و کلیدهای میان‌بر

در جاوااسکریپت، با استفاده از کد زیر می‌توان دسترسی به منوی راست‌کلیک و برخی کلیدهای ترکیبی مانند F۱۲ یا Ctrl + Shift + I را مسدود کرد:

document.addEventListener('contextmenu', event => event.preventDefault());

document.addEventListener('keydown', event => {
if (event.key === 'F12' || (event.ctrlKey && event.shiftKey && event.key === 'I')) {
event.preventDefault();
}
});



#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
👍1
کتاب Chibi Vue نوشته‌ی یویچی کیکوچی، راهنمایی جامع و دقیق درباره‌ی ساختار درونی فریم‌ورک Vue ۳ است. این کتاب به‌ویژه برای توسعه‌دهندگانی که به‌صورت عمیق در حال یادگیری Vue هستند، بسیار سودمند است.

در این کتاب می‌خوانید:

تحلیل جامع هسته‌ی Vue، شامل: سامانه‌ی واکنش‌پذیری، کامپایلر قالب‌ها، و سیستم رندرینگ.

پیاده‌سازی عملی و گام‌به‌گام نسخه‌ای ساده‌شده از Vue از ابتدا.

زبان این کتاب انگلیسی است.
🔗https://book.chibivue.land/
#️⃣#tip #vue
👥@IR_javascript_group
🆔@IR_javascript
This media is not supported in your browser
VIEW IN TELEGRAM
💚میلاد امام رضا علیه السلام مبارک باد
🔻برخورد زیبای امام رضا(ع) به کسی که با بی‌رحمی خانه‌اش را غارت کرد.

🔗 [+لینک ویدیو]
#️⃣#event
👥@IR_javascript_group
🆔@IR_javascript
10
کار با عددها و تاریخ‌ها در عناصر <input> می‌تواند بسیار ساده‌تر از چیزی باشد که معمولاً انجام می‌دهیم.

به‌طور پیش‌فرض، وقتی مقدار یک <input> را می‌گیریم، آن را به صورت رشته (string) دریافت می‌کنیم:

const raw = myInput.value; // نوع string


اگر این مقدار در واقع یک عدد یا تاریخ باشد، ناچاریم آن را به‌صورت دستی تبدیل (parse) کنیم:

const num = Number(myInput.value);
const date = new Date(myInput.value);


این کار تا حدی تکراری و خسته‌کننده به نظر می‌رسد، درست است؟
اینجاست که دو ویژگی ویژه به کمکمان می‌آیند:
valueAsNumber و valueAsDate

---

### valueAsNumber — تبدیل خودکار به عدد، بدون نیاز به parseInt یا parseFloat

// به‌جای:
const num = Number(myInput.value);

// استفاده از:
const num = myInput.valueAsNumber; // عدد یا NaN


اگر ورودی چیزی باشد که به‌درستی قابل تبدیل به عدد نباشد، مقدار NaN بازگردانده می‌شود، که می‌توان با استفاده از isNaN(num) آن را بررسی کرد.

این ویژگی فقط مختص type="number" نیست، بلکه برای type="range" نیز کار می‌کند.

---

### valueAsDate — دریافت مستقیم یک شیء Date

// به‌جای:
const dt = new Date(myInput.value);

// استفاده از:
const dt = myInput.valueAsDate; // شیء Date یا null


اگر فیلد خالی باشد، مقدار بازگشتی null خواهد بود. بررسی آن نیز ساده است:

if (!dt) {
// مقدار تاریخ وارد نشده است
}


نکته مهم اینجاست که تاریخ‌ها به‌صورت زمان UTC (ساعت صفر به وقت هماهنگ جهانی) در نظر گرفته می‌شوند.
برای نمایش محلی، از متدهای toLocaleString() یا توابعی مانند getUTCFullYear() استفاده کنید.

---

### نتیجه:

با استفاده از valueAsNumber و valueAsDate می‌توانیم از نوشتن کدهای اضافی مانند Number(...) یا new Date(...) خلاص شویم و کدی تمیزتر و خواناتر بنویسیم.

#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
🔥2👍1
جاوااسکریپت | JavaScript pinned «لیستی از سایت هایی که در آنها می توانید آموزش های رایگان پیدا کنید https://downloadly.ir/ https://www.bilibili.com/ https://oneddl.net/?do=search https://oneddl.org/search/Computer+Networking/ https://www.avxgfx.com/video_tutorials/ https://www.4shared.com/…»
قالب‌های HTML

یکی از روش‌های مؤثر برای سامان‌دهی کد HTML، استفاده از *قالب‌ها*ست؛ این تکنیک به کاهش تکرار، تقسیم‌بندی منطقی کد و در نهایت بهبود درک ساختار صفحه کمک می‌کند.

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

### چگونه کار می‌کند؟

برای ایجاد قالب، از تگ <template> استفاده می‌کنیم. به‌عنوان مثال:

<template id="tmp">
<h1>عنوان</h1>
<p>متن...</p>
</template>


### استفاده از قالب:

برای استفاده از محتوای یک قالب، کافی‌ست آن را *کلون* کرده و در جای دلخواه در صفحه قرار دهید. این کار امکان استفاده‌ی چندباره از یک بخش مشخص از کد را فراهم می‌سازد:

let elem = document.createElement('div');
elem.append(tmp.content.cloneNode(true));
document.body.append(elem);


نکته مهم:
مرورگر محتویات تگ <template> را نادیده می‌گیرد و تنها از نظر نحوی (syntax) بررسی می‌کند. این بدان معناست که کد داخل قالب تا زمانی که فعالانه در صفحه درج نشود، اجرا یا نمایش داده نمی‌شود.




#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
👍1
نتیجه چه خواهد بود؟

"🤦‍♂️".substr(0,2);
"🤦‍♂️".substr(2,3);

#️⃣#code
👥@IR_javascript_group
🆔@IR_javascript
چه چیزی DOM است و چرا به آن نیاز داریم؟

«همه‌جا صحبت از DOM است... اما واقعاً DOM چیست؟»

DOM (مخفف *Document Object Model*) یا مدل شیء‌گرای سند، نمایی ساختاری از یک صفحه وب به شکل یک درخت است. در این مدل، هر تگ HTML به یک گره تبدیل می‌شود—یا شاخه، یا برگ. این ساختار به JavaScript اجازه می‌دهد تا در میان این درخت حرکت کرده، ویژگی‌های گره‌ها را بخواند و ساختار یا محتوای آن‌ها را در لحظه تغییر دهد.

### چرا به DOM نیاز داریم؟

پویایی محتوا

* امکان تغییر متن، سبک‌ها و ساختار صفحه بدون نیاز به بارگذاری مجدد
* پیاده‌سازی برنامه‌های تک‌صفحه‌ای (*SPA*) و رابط‌های فوق‌العاده سریع

تعامل‌پذیری

* واکنش به کلیک، حرکت ماوس، یا ورود اطلاعات از صفحه‌کلید
* ساخت منوهای کشویی، پنجره‌های مودال، اسلایدرها و سایر قابلیت‌هایی که به یک وب‌سایت «جان» می‌بخشند

ارتباط با JavaScript

* DOM پلی است میان HTML و CSS ایستا با منطق پویا در JavaScript
* این امکان را به اسکریپت‌ها می‌دهد که عناصر را جابه‌جا کرده، حذف یا اضافه کنند و به آن‌ها انیمیشن بدهند


### نکات مهم:

هنگامی که شروع به اعمال تغییرات متعدد در DOM می‌کنید، به خاطر داشته باشید که هر تغییر می‌تواند پرهزینه باشد. افزودن یا حذف عناصر، تغییر در سبک‌ها یا بازآرایی ساختار صفحه، باعث رخ دادن «بازمحاسبه» (*reflow*) و «بازنقاشی» (*repaint*) می‌شود—یعنی مرورگر مجبور است دوباره ابعاد و موقعیت عناصر را محاسبه کرده و صفحه را مجدداً ترسیم کند. اگر این تغییرات زیاد و پراکنده باشند، ممکن است باعث کند شدن رابط کاربری شود.

برای جلوگیری از این مشکل، سعی کنید تغییرات را دسته‌بندی و یکجا اعمال کنید؛ به عنوان مثال، ابتدا گره‌های جدید را در یک *DocumentFragment* قرار دهید و سپس آن را به‌صورت یکجا به DOM اضافه کنید، به‌جای آنکه هر گره را جداگانه درج نمایید.

نکته‌ای دیگر، مسئله امنیت است. استفاده‌ی مستقیم از innerHTML برای درج کد HTML، می‌تواند زمینه‌ساز حملات XSS شود. اگر کدی مخرب وارد شود، ممکن است در صفحه شما اجرا گردد. برای جلوگیری از این خطر، به‌جای innerHTML از textContent برای درج متن استفاده کنید و برای ایجاد عناصر جدید، از document.createElement و روش‌هایی مانند appendChild یا insertBefore بهره بگیرید.

### جمع‌بندی:

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




#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
This media is not supported in your browser
VIEW IN TELEGRAM
:hover > \:not(\:hover)
معمولاً از ویژگی hover برای برجسته‌سازی یک عنصر خاص استفاده می‌شود؛ اما گاهی‌اوقات زیباتر است اگر به‌جای آن، کاری با سایر عناصر انجام دهیم.

CSS

ul {
@media (hover) and (prefers-reduced-motion: no-preference) {
& > li {
transform-origin: left center;
transition: transform یک ثانیه با تابع زمان‌بندی var(--ease-spring-۳)،
opacity صفر ممیز سه ثانیه با تابع زمان‌بندی var(--ease-۳);
}
&:hover > li:not(:hover) {
opacity: ۰.۲۵;
transform: scale(۰.۸);
}
}
}


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


#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
👍4
افزونه‌هایی مفید برای vscode:

Angular Language Service – پیشنهاد خودکار کد و امکان پیمایش آسان بین کامپوننت‌ها

ESLint + Prettier – کدی پاک و یکپارچه، بدون نیاز به تلاش اضافی

Import/Export Sorter برای JavaScript/TypeScript – مرتب‌سازی خودکار import و export هنگام ذخیره‌سازی

Path IntelliSense – تکمیل خودکار مسیر فایل‌ها با سرعت و دقت

Gremlins – هشدار در صورت وارد کردن اشتباه حروف، مانند تایپ «С» روسی به‌جای «C» انگلیسی

GitLen‎s – مشاهده‌ی تاریخچه تغییرات در کد: چه کسی، چه زمانی، چه چیزی را تغییر داده است


Run Terminal Command — امکان اجرای مستقیم دستورات (مثل npm، ng، یا git) از طریق منوی زمینه‌ی فایل‌ها یا از پنل فرمان را فراهم می‌کند.

CSS Peek — اجازه می‌دهد از کلاس‌ها یا شناسه‌های (id) موجود در HTML، مستقیماً به محل تعریف آن‌ها در فایل‌های CSS یا SCSS بروید.

Import ‎Cost — اندازه‌ی هر ماژول واردشده را نمایش می‌دهد و کمک می‌کند وابستگی‌های «سنگین» پروژه را تحت کنترل داشته باشید.


#️⃣#tool
👥@IR_javascript_group
🆔@IR_javascript
رویداددهی تفویضی (Event Delegation) چیست؟
رویداددهی تفویضی یا Event Delegation تکنیکی در برنامه‌نویسی است که به‌جای آن‌که برای هر عنصر تعاملی (دکمه، لینک، آیتم فهرست و غیره) یک شنونده‌ی رویداد (event listener) جداگانه تعریف کنیم، یک شنونده‌ی واحد را روی عنصر والد آن‌ها (یا حتی روی کل سند document) قرار می‌دهیم.
زمانی که کاربر روی یک عنصر فرزند کلیک می‌کند، رویداد به سمت بالا در سلسله‌مراتب عناصر حرکت می‌کند (این پدیده به نام *Event Bubbling* شناخته می‌شود)، و ما می‌توانیم آن را در نقطه‌ای بالاتر دریافت و مدیریت کنیم.

### چرا این روش مفید است؟

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

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

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

---

### چند نکته‌ی کاربردی:

* از e.target.matches() استفاده کنید
برای آن‌که تشخیص دهید رویداد دقیقاً روی کدام عنصر اتفاق افتاده است.

* از closest() بهره بگیرید
برای پیدا کردن نزدیک‌ترین عنصر والد مانند یک <li> که حاوی دکمه یا عنصر موردنظر باشد.

* محدوده‌ی تفویض را هوشمندانه انتخاب کنید
نیازی نیست شنونده را روی کل سند (document) قرار دهید؛ اگر می‌توان آن را به نزدیک‌ترین والد مشترک محدود کرد، از این کار بهره‌مند شوید تا از پردازش‌های غیرضروری جلوگیری شود.

---

### جمع‌بندی

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


#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
بررسی Type Guardهای امن در TypeScript برای مقادیر unknown یا any

در اینجا به یکی از ویژگی‌های موردعلاقه‌ام در TypeScript می‌پردازم:
استفاده از عبارت value is Type که به کامپایلر کمک می‌کند تا نوع واقعی یک مقدار را شناسایی کرده و بدون نیاز به تبدیل‌های پرخطر از نوع any یا بروز خطاهای زمان اجرا، با آن کار کند.

### چرا نباید از as به‌صورت سرسری استفاده کنیم؟

اغلب هنگام مواجهه با مقادیر از نوع unknown یا `any`، خیلی ساده می‌نویسیم:

const data = value as MyType;


یا حتی:

const data = value as any;


در این حالت، در واقع چشم خود را بر هشدارهای کامپایلر می‌بندیم. اما این کار باعث می‌شود از مزایای سیستم نوع‌گذاری TypeScript محروم شویم و ممکن است در زمان اجرا با مقدار `undefined` به‌جای فیلدی که انتظار داریم، مواجه شویم.

### راه‌حل: استفاده از تابع تشخیص (Type Predicate)

به‌جای تبدیل‌های کورکورانه، می‌توانیم با صرف کمی وقت بیشتر، تابعی بنویسیم که:

۱. بررسی کند مقدار null یا undefined نباشد
۲. وجود ویژگی‌های موردنیاز را بررسی کند
۳. نوع این ویژگی‌ها را با دقت بررسی نماید (مثلاً string، number، و غیره)

### نمونه‌ای از یک بررسی امن:

function isMyType(value: unknown): value is MyType {
return (
typeof value === 'object' &&
value !== null &&
/* بررسی وجود ویژگی‌ها */
/* بررسی نوع اولیه‌ی آن‌ها */
);
}


در اینجا:

* value: unknown یعنی ما به ورودی اعتماد نداریم.
* value is MyType به کامپایلر قول می‌دهد: «اگر خروجی true بود، قطعاً نوع مقدار MyType است».
* درون تابع، می‌توانیم از انواع بررسی‌ها استفاده کنیم: بررسی کلیدها، استفاده از instanceof`، `Array.isArray() و هر روش منطقی دیگری.

### یک مثال واقعی از کاربرد:

function handle(resp: unknown) {
if (isMyType(resp)) {
// در اینجا مطمئن هستیم که resp از نوع MyType است
// بنابراین می‌توانیم با خیال راحت از ویژگی‌های آن استفاده کنیم
}
}


### نتیجه‌گیری

این روش، راهکاری مؤثر برای حفظ ایمنی نوع‌ها هنگام کار با مقادیر unknown یا any است. نه‌تنها به کدی مطمئن‌تر منجر می‌شود، بلکه تجربه‌ی توسعه را نیز با خطاهای کمتر و پیش‌بینی‌پذیری بیشتر بهبود می‌بخشد.



#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
دسترس‌پذیری وب‌سایت و نقش ویژگی‌های ARIA

به‌تازگی شروع کرده‌ام درباره‌ی اهمیت دسترس‌پذیری وب‌سایت‌ها صحبت کنم. امروز این موضوع را ادامه می‌دهم و درباره‌ی ویژگی‌های ARIA توضیح می‌دهم؛ عناصری کلیدی که باعث می‌شوند رابط‌های کاربری وب برای همه‌ی کاربران قابل فهم باشند.

ARIA (مخفف *برنامه‌های اینترنتی غنی قابل دسترس*) مجموعه‌ای از ویژگی‌هاست که به عناصر HTML افزوده می‌شود تا فناوری‌های کمکی مانند صفحه‌خوان‌ها، نمایشگرهای بریل و ابزارهای مشابه، اطلاعات بیشتری درباره‌ی نقش و وضعیت عناصر رابط کاربری دریافت کنند.

مثالی بدون استفاده از ARIA:
فرض کنید یک دکمه‌ی چندرسانه‌ای داریم که به هر دلیلی فقط با یک عنصر <div> ساخته شده است. در این حالت، یک صفحه‌خوان قادر نخواهد بود تشخیص دهد که این عنصر در واقع یک دکمه است.

نمونه‌ی بهبودیافته با استفاده از ARIA:
در این مثال ما صراحتاً مشخص می‌کنیم که این عنصر یک دکمه است:

<div role="button" tabindex="0">Play</div>


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

#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
👍1
رنگ currentColor
یکی از قابلیت‌های CSS که گاهی فراموش می‌شود، اما می‌تواند در مدیریت رنگ‌ها بسیار مفید واقع شود، ویژگی currentColor است.

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

این ویژگی، یک واژه‌ی کلیدی خاص در CSS است که برای ارجاع به رنگ فعلی عنصر به کار می‌رود.

به عنوان مثال، اگر رنگ متن یک عنصر با استفاده از ویژگی color تعیین شده باشد، currentColor به همان رنگ اشاره خواهد کرد، فارغ از این‌که در کجا یا چگونه مورد استفاده قرار می‌گیرد.

چه زمانی باید از currentColor استفاده کرد؟
زمانی که می‌خواهید رنگ متن، حاشیه و سایر ویژگی‌ها یکسان باشند و به‌راحتی قابل تغییر باشند.

در فایل‌های SVG نیز می‌توان رنگ پرشدگی یا خط دور عناصر را با currentColor تعیین کرد. این موضوع زمانی بسیار کاربردی است که نیاز دارید رنگ آیکون با رنگ متن یا سایر عناصر هماهنگ باشد.

مثال:

button {
color: blue; /* تعیین رنگ متن */
background-color: white;
border: ۲px solid currentColor; /* حاشیه به رنگ آبی، همانند رنگ متن خواهد بود */
}

svg {
fill: currentColor; /* آیکون به رنگ آبی، همانند رنگ متن نمایش داده می‌شود */
}


در مجموع، استفاده از currentColor روشی عالی برای بهبود مدیریت سبک‌ها و کاهش تکرار در کدنویسی است.




#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
👍31