در این مطلب میخواهیم درباره دو هوک کاربردی در Vue به نامهای
### این دو چه کاری انجام میدهند؟
- `onRenderTracked`: نشان میدهد که Vue هنگام رندر شدن، چه چیزهایی را دنبال و رصد میکند (یعنی چه چیزی را "ردگیری" میکند).
- `onRenderTriggered`: مشخص میکند که چه چیزی تغییر کرده و باعث اجرای مجدد رندر شده است.
### چه زمانی باید از آنها استفاده کرد؟
- زمانی که یک کامپوننت بیش از حد و بدون دلیل واضحی رندر میشود.
- وقتی قصد بهینهسازی عملکرد (Performance Debugging) را دارید.
- زمانی که مشغول بررسی کدی هستید که توسط فرد دیگری نوشته شده یا خودتان مدتی پیش نوشتهاید و حالا علت رفتارهای آن را نمیدانید.
### نمونهای از استفاده:
زمانی که روی دکمه کلیک میکنید، در کنسول پیغامی مشابه زیر نمایش داده میشود:
### چه چیزی در این هوکها به شما داده میشود؟
Vue یک شیء با فیلدهای زیر به شما تحویل میدهد:
-
-
-
-
-
### چه کاربردهای مفیدی دارند؟
#### شناسایی رندرهای غیرضروری
فرض کنید کامپوننت شما هنگام تغییر یک متغیر رندر میشود، در حالی که آن متغیر اصلاً در قالب (template) استفاده نشده. در این حالت میتوانید با استفاده از
#### لاگگیری وابستگیها
میتوانید اطلاعات ردیابیشده را در قالب جدول چاپ کنید تا راحتتر متوجه شوید کامپوننت شما چه چیزهایی را دنبال میکند:
#### تحلیل عملکرد
میتوانید شمارندهای برای تعداد دفعات اجرای
---
### خلاصه:
-
-
- این ابزارها برای دیباگ و بهینهسازی بسیار کاربردی هستند.
- فقط در حالت توسعه (dev mode) استفاده شوند.
#️⃣#tip #vue
👥@IR_javascript_group
🆔@IR_javascript
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 آن را از بین نمیبرد، بلکه بهآرامی کنار میگذارد تا در صورت نیاز دوباره مورد استفاده قرار گیرد. عملکرد آن شبیه به
### کاربرد رایج:
فرض کنید در برنامه خود از زبانهها (Tabs) یا مسیرها (Routes) استفاده میکنید و میخواهید هنگام جابهجایی بین زبانهها، اطلاعات واردشده، موقعیت اسکرول و سایر وضعیتها حفظ شوند:
### اگر بخواهم کنترل کنم چه چیزی کش شود، چه کنم؟
از نسخه دو ممیز یک ممیز صفر به بعد،
#### نمونهها:
رشتهای از نامها (با ویرگول جدا شده):
عبارت منظم (Regex):
آرایهای از نامها:
### همچنین میتوانید از prop به نام
---
### چه چیزهایی در Vue ۳ جدید است؟
در گذشته، یک کامپوننت یا کش میشد یا نمیشد — همین! اما در Vue ۳، امکانات بیشتری برای کنترل رفتار فراهم شده است.
### رفتار جدید: هوکهای
وقتی یک کامپوننت در
این یعنی شما میتوانید:
- تایمرها را موقتاً متوقف کنید
- از منابع سنگین جدا شوید (unsubscribe)
- انیمیشنها را متوقف کرده یا به حالت تعلیق درآورید
### چه زمانی بهتر است استفاده نشود؟
- زمانی که کامپوننت "ارزان" است و رندر شدن آن زمان زیادی نمیبرد
- زمانی که حفظ وضعیت کامپوننت برایتان اهمیتی ندارد
- زمانی که میخواهید کامپوننت با هر بار نمایش، کاملاً از نو ساخته شود
---
### خلاصهی مطالب:
-
- از
- امکان فیلتر کردن کامپوننتها با
- میتوان با
- فقط با یک فرزند (یا تگ
#️⃣#tip #vue
👥@IR_javascript_group
🆔@IR_javascript
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
گاهی اوقات هنگام نوشتن یک کامپوننت، انواع ویژگیها مانند
### دقیقاً چه اتفاقی میافتد؟
Vue تمامی ویژگیهایی را که صراحتاً بهعنوان props تعریف نکردهاید**، جمعآوری کرده و آنها را روی **المان ریشهای (Root Element) کامپوننت شما قرار میدهد.
#### مثال:
و درون
در این صورت، ویژگیهای
ساده و کاربردی، نه؟
---
### اگر از ساختار سفارشی استفاده کرده باشم چه میشود؟
اگر نخواهید Vue بهطور خودکار این ویژگیها را به هر جایی منتقل کند و ترجیح دهید خودتان تعیین کنید این ویژگیها به کدام عنصر بروند**، در این صورت میتوانید از `v-bind="$attrs"` استفاده کنید.
#### نمونه:
در اینجا فقط دکمه دوم ویژگیهایی مثل `id` و `class` را دریافت میکند.
---
### اگر اصلاً نخواهید Vue چیزی منتقل کند چه؟
اگر بخواهید کنترل کامل را در دست داشته باشید، میتوانید انتقال خودکار ویژگیها را غیرفعال کنید. کافیست گزینه زیر را در کامپوننتتان اضافه کنید:
در این حالت، **هیچ ویژگیای به عنصر ریشهای (div) اضافه نمیشود و تنها به دکمه منتقل خواهد شد. این کار زمانی بسیار مفید است که بخواهید استایلها یا رویدادها دقیقاً روی یک عنصر تعاملی مثل دکمه اعمال شوند.
---
### نکات مهم:
- هر چیزی که prop نباشد، در
- بهصورت پیشفرض، تمام این ویژگیها به عنصر ریشهای کامپوننت افزوده میشوند.
- اگر میخواهید کنترل بیشتری داشته باشید، از
- میتوان
- اگر نام یک ویژگی با نام prop یکی باشد، آن ویژگی دیگر وارد
این ویژگیها به شما کمک میکنند کنترل دقیقتری بر ساختار، استایل و رفتار کامپوننتهای خود داشته باشید — خصوصاً در کامپوننتهای قابل استفاده مجدد و پیچیده.
#️⃣#tip #vue
👥@IR_javascript_group
🆔@IR_javascript
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
کتاب Chibi Vue نوشتهی یویچی کیکوچی، راهنمایی جامع و دقیق دربارهی ساختار درونی فریمورک Vue ۳ است. این کتاب بهویژه برای توسعهدهندگانی که بهصورت عمیق در حال یادگیری Vue هستند، بسیار سودمند است.
در این کتاب میخوانید:
تحلیل جامع هستهی Vue، شامل: سامانهی واکنشپذیری، کامپایلر قالبها، و سیستم رندرینگ.
پیادهسازی عملی و گامبهگام نسخهای سادهشده از Vue از ابتدا.
زبان این کتاب انگلیسی است.
🔗https://book.chibivue.land/
#️⃣#tip #vue
👥@IR_javascript_group
🆔@IR_javascript
در این کتاب میخوانید:
تحلیل جامع هستهی Vue، شامل: سامانهی واکنشپذیری، کامپایلر قالبها، و سیستم رندرینگ.
پیادهسازی عملی و گامبهگام نسخهای سادهشده از Vue از ابتدا.
زبان این کتاب انگلیسی است.
🔗https://book.chibivue.land/
#️⃣#tip #vue
👥@IR_javascript_group
🆔@IR_javascript
chibivue
Writing Vue.js: Step by Step, from just one line of "Hello, World".
متوقف کردن یک Watcher
Watcher**هایی که بهصورت همزمان (synchronous) درون تابع `setup()` یا در قالب `<script setup>` تعریف میشوند، به نمونه (instance) کامپوننت مالک وابسته هستند و بهطور خودکار هنگام **unmount شدن آن کامپوننت متوقف خواهند شد. در اغلب موارد، نیازی نیست نگران متوقف کردن دستی آنها باشید.
نکتهی کلیدی در اینجاست که Watcher باید بهصورت همزمان ایجاد شود؛ اگر Watcher در یک تابع غیرهمزمان (asynchronous) مانند
برای متوقف کردن دستی یک Watcher**، میتوان از تابع بازگشتی استفاده کرد. این روش هم برای `watch` و هم برای `watchEffect` کاربرد دارد:
توجه داشته باشید که تنها در موارد بسیار محدود نیاز به ایجاد **Watcher بهصورت غیرهمزمان وجود دارد، و در هر زمان ممکن، بهتر است از ایجاد همزمان استفاده شود.
اگر نیاز دارید منتظر دادهای غیرهمزمان بمانید، میتوانید منطق Watcher خود را مشروط طراحی کنید:
#️⃣#tip #vue
👥@IR_javascript_group
🆔@IR_javascript
Watcher**هایی که بهصورت همزمان (synchronous) درون تابع `setup()` یا در قالب `<script setup>` تعریف میشوند، به نمونه (instance) کامپوننت مالک وابسته هستند و بهطور خودکار هنگام **unmount شدن آن کامپوننت متوقف خواهند شد. در اغلب موارد، نیازی نیست نگران متوقف کردن دستی آنها باشید.
نکتهی کلیدی در اینجاست که Watcher باید بهصورت همزمان ایجاد شود؛ اگر Watcher در یک تابع غیرهمزمان (asynchronous) مانند
setTimeout
ایجاد گردد، دیگر به کامپوننت والد وابسته نخواهد بود و باید بهصورت دستی متوقف شود تا از نشت حافظه (memory leak) جلوگیری شود. به مثال زیر توجه کنید:<script setup>
import { watchEffect } from 'vue'
// این Watcher بهصورت خودکار متوقف خواهد شد
watchEffect(() => {})
// ...اما این یکی نه!
setTimeout(() => {
watchEffect(() => {})
}, ۱۰۰)
</script>
برای متوقف کردن دستی یک Watcher**، میتوان از تابع بازگشتی استفاده کرد. این روش هم برای `watch` و هم برای `watchEffect` کاربرد دارد:
const unwatch = watchEffect(() => {})
// ...در زمانی دیگر، زمانی که دیگر نیازی نیست
unwatch()
توجه داشته باشید که تنها در موارد بسیار محدود نیاز به ایجاد **Watcher بهصورت غیرهمزمان وجود دارد، و در هر زمان ممکن، بهتر است از ایجاد همزمان استفاده شود.
اگر نیاز دارید منتظر دادهای غیرهمزمان بمانید، میتوانید منطق Watcher خود را مشروط طراحی کنید:
// دادهای که بهصورت غیرهمزمان بارگذاری میشود
const data = ref(null)
watchEffect(() => {
if (data.value) {
// انجام عملیات زمانی که داده بارگذاری شد
}
})
#️⃣#tip #vue
👥@IR_javascript_group
🆔@IR_javascript
❤1👍1
در هنگام استفاده از
تنها راهحل مؤثری که تاکنون یافته شده، غیرفعال کردن این حالت (mode) در زمان توسعه است.
نمونهای از کد مربوطه:
در این وضعیت، پیشنهاد میشود برای جلوگیری از بروز مشکل، در محیط توسعه از مقدار پیشفرض
#️⃣#tip #vue
👥@IR_javascript_group
🆔@IR_javascript
router-view
همراه با transition
و تعیین `mode="out-in"`، در حالت توسعه (dev mode)، هنگام جابهجایی بین مسیرها (routes) اغلب با مشکل نمایش صفحه سفید مواجه میشویم.تنها راهحل مؤثری که تاکنون یافته شده، غیرفعال کردن این حالت (mode) در زمان توسعه است.
نمونهای از کد مربوطه:
<router-view v-slot="{ Component }">
<Transition mode="out-in">
<component :is="Component" />
</Transition>
</router-view>
در این وضعیت، پیشنهاد میشود برای جلوگیری از بروز مشکل، در محیط توسعه از مقدار پیشفرض
mode
یا از حالتهایی مانند "in-out"
یا بدون مشخصکردن mode
استفاده شود و تنها در محیط تولید (production) از حالت out-in
بهره بگیرید، چرا که این حالت در محیط توسعه ممکن است باگهایی مانند نمایش صفحه سفید موقت ایجاد کند.#️⃣#tip #vue
👥@IR_javascript_group
🆔@IR_javascript
👍3❤1