در این پست، API جدیدی با نام effectScope() برای پکیج @vue/reactivity معرفی میشود. یک نمونه از EffectScope میتواند بهصورت خودکار، افکتهایی را که درون یک تابع همزمان اجرا میشوند، گردآوری کند تا در زمان مناسب همگی با هم حذف شوند.
در تابع setup() درون یک کامپوننت Vue، افکتها بهصورت خودکار جمعآوری شده و به همان نمونهی کامپوننت متصل میشوند. هنگام از بین رفتن کامپوننت، این افکتها نیز بهطور خودکار حذف میشوند. این ویژگی، ساده و شهودی است.
اما هنگامی که این افکتها را خارج از کامپوننتها یا در قالب یک پکیج مستقل استفاده کنیم، کار به این سادگی نیست. برای نمونه، حذف افکتهای computed و watch به صورت دستی به شکل زیر خواهد بود:
و برای حذف آنها:
بهویژه در کدهای ترکیبی طولانی، جمعآوری دستی افکتها کاری زمانبر و مستعد خطاست. فراموشکردن این کار یا نداشتن دسترسی به افکتهای ایجادشده، میتواند منجر به نشتی حافظه یا رفتارهای غیرمنتظره شود.
اما با وجود EffectScope بصورت زیر میشود
### Scopeهای تودرتو
Scopeهای تودرتو نیز باید توسط scope والد جمعآوری شوند. زمانی که scope والد حذف شود، همهی scopeهای فرزند نیز حذف خواهند شد:
---
### Scopeهای جداشده (Detached)
پارامتر
---
### تابع onScopeDispose
تابع
---
### دریافت scope فعلی
API جدید
🔗https://github.com/vuejs/rfcs/blob/master/active-rfcs/0041-reactivity-effect-scope.md
#️⃣#tip #vue
👥@IR_javascript_group
🆔@IR_javascript
در تابع setup() درون یک کامپوننت Vue، افکتها بهصورت خودکار جمعآوری شده و به همان نمونهی کامپوننت متصل میشوند. هنگام از بین رفتن کامپوننت، این افکتها نیز بهطور خودکار حذف میشوند. این ویژگی، ساده و شهودی است.
اما هنگامی که این افکتها را خارج از کامپوننتها یا در قالب یک پکیج مستقل استفاده کنیم، کار به این سادگی نیست. برای نمونه، حذف افکتهای computed و watch به صورت دستی به شکل زیر خواهد بود:
const disposables = []
const counter = ref(۰)
const doubled = computed(() => counter.value * ۲)
disposables.push(() => stop(doubled.effect))
const stopWatch۱ = watchEffect(() => {
console.log(`counter: ${counter.value}`)
})
disposables.push(stopWatch۱)
const stopWatch۲ = watch(doubled, () => {
console.log(doubled.value)
})
disposables.push(stopWatch۲)
و برای حذف آنها:
disposables.forEach((f) => f())
disposables = []
بهویژه در کدهای ترکیبی طولانی، جمعآوری دستی افکتها کاری زمانبر و مستعد خطاست. فراموشکردن این کار یا نداشتن دسترسی به افکتهای ایجادشده، میتواند منجر به نشتی حافظه یا رفتارهای غیرمنتظره شود.
اما با وجود EffectScope بصورت زیر میشود
// effect، computed، watch، و watchEffect که درون این scope ساخته میشوند، جمعآوری خواهند شد
const scope = effectScope()
scope.run(() => {
const doubled = computed(() => counter.value * ۲)
watch(doubled, () => console.log(doubled.value))
watchEffect(() => console.log('تعداد: ', doubled.value))
})
// برای حذف همه افکتها در این scope
scope.stop()
### Scopeهای تودرتو
Scopeهای تودرتو نیز باید توسط scope والد جمعآوری شوند. زمانی که scope والد حذف شود، همهی scopeهای فرزند نیز حذف خواهند شد:
const scope = effectScope()
scope.run(() => {
const doubled = computed(() => counter.value * ۲)
effectScope().run(() => {
watch(doubled, () => console.log(doubled.value))
})
watchEffect(() => console.log('تعداد: ', doubled.value))
})
// حذف تمام افکتها، از جمله موارد در scopeهای تودرتو
scope.stop()
---
### Scopeهای جداشده (Detached)
پارامتر
detached
در effectScope
اجازه میدهد تا scope بهصورت جدا از scope والد ایجاد شود. این ویژگی برای سناریوهایی مانند «مقداردهی اولیه تنبل» (Lazy Initialization) مفید است.let nestedScope
const parentScope = effectScope()
parentScope.run(() => {
const doubled = computed(() => counter.value * ۲)
nestedScope = effectScope(true /* detached */)
nestedScope.run(() => {
watch(doubled, () => console.log(doubled.value))
})
watchEffect(() => console.log('تعداد: ', doubled.value))
})
// فقط scope والد حذف میشود
parentScope.stop()
// scope تودرتو را در زمان مناسب حذف میکنیم
nestedScope.stop()
---
### تابع onScopeDispose
تابع
onScopeDispose
عملکردی مشابه onUnmounted
دارد، اما برای scope فعلی (نه نمونه کامپوننت). این قابلیت به فانکشنهای ترکیبی کمک میکند تا اثرات جانبی خود را همراه با scope مربوطه پاکسازی کنند.import { onScopeDispose } from 'vue'
const scope = effectScope()
scope.run(() => {
onScopeDispose(() => {
console.log('پاکسازی شد!')
})
})
scope.stop() // چاپ: پاکسازی شد!
---
### دریافت scope فعلی
API جدید
getCurrentScope()
برای دریافت scope فعلی معرفی شده است:import { getCurrentScope } from 'vue'
getCurrentScope() // EffectScope | undefined
🔗https://github.com/vuejs/rfcs/blob/master/active-rfcs/0041-reactivity-effect-scope.md
#️⃣#tip #vue
👥@IR_javascript_group
🆔@IR_javascript
GitHub
rfcs/active-rfcs/0041-reactivity-effect-scope.md at master · vuejs/rfcs
RFCs for substantial changes / feature additions to Vue core - vuejs/rfcs
### مثالها
#### مثال الف: استفادهی مشترک از composable
تابع
اگر
ابتدا:
سپس یک تابع کمکی برای مدیریت اشتراک ایجاد میکنیم:
اکنون:
این نسخه از
---
#### مثال ب: Scopeهای موقتی (Ephemeral)
در اینجا scopeها بهصورت موقتی ساخته و حذف میشوند.
---
### تأثیر در هسته Vue
در حال حاضر، در
با پیادهسازی این RFC، دیگر نیازی به بازنویسی
🔗https://github.com/vuejs/rfcs/blob/master/active-rfcs/0041-reactivity-effect-scope.md
#️⃣#tip #vue
👥@IR_javascript_group
🆔@IR_javascript
#### مثال الف: استفادهی مشترک از composable
تابع
useMouse()
یک نمونهی خوب برای ایجاد اثرات جانبی جهانی است:function useMouse() {
const x = ref(۰)
const y = ref(۰)
function handler(e) {
x.value = e.x
y.value = e.y
}
window.addEventListener('mousemove', handler)
onUnmounted(() => {
window.removeEventListener('mousemove', handler)
})
return { x, y }
}
اگر
useMouse()
در چند کامپوننت فراخوانی شود، هرکدام یک listener جدید ایجاد کرده و refs جداگانه خواهند داشت. برای جلوگیری از این کار پرهزینه، میتوانیم از scope جداشده و onScopeDispose
استفاده کنیم:ابتدا:
- onUnmounted(() => {
+ onScopeDispose(() => {
window.removeEventListener('mousemove', handler)
})
سپس یک تابع کمکی برای مدیریت اشتراک ایجاد میکنیم:
function createSharedComposable(composable) {
let subscribers = ۰
let state, scope
const dispose = () => {
if (scope && --subscribers <= ۰) {
scope.stop()
state = scope = null
}
}
return (...args) => {
subscribers++
if (!state) {
scope = effectScope(true)
state = scope.run(() => composable(...args))
}
onScopeDispose(dispose)
return state
}
}
اکنون:
const useSharedMouse = createSharedComposable(useMouse)
این نسخه از
useMouse
تنها یک بار listener را اضافه میکند و در صورت عدم نیاز، آن را حذف مینماید.---
#### مثال ب: Scopeهای موقتی (Ephemeral)
export default {
setup() {
const enabled = ref(false)
let mouseState, mouseScope
const dispose = () => {
mouseScope && mouseScope.stop()
mouseState = null
}
watch(
enabled,
() => {
if (enabled.value) {
mouseScope = effectScope()
mouseState = mouseScope.run(() => useMouse())
} else {
dispose()
}
},
{ immediate: true }
)
onScopeDispose(dispose)
},
}
در اینجا scopeها بهصورت موقتی ساخته و حذف میشوند.
onScopeDispose
اطمینان حاصل میکند که useMouse
بهدرستی پاکسازی شود، درحالیکه onUnmounted
در این فرآیند فراخوانی نمیشود.---
### تأثیر در هسته Vue
در حال حاضر، در
@vue/runtime-dom
توابع computed
بازنویسی میشوند تا به نمونهی کامپوننت متصل شوند. بنابراین موارد زیر معادل نیستند:// متفاوت
import { computed } from '@vue/reactivity'
import { computed } from 'vue'
با پیادهسازی این RFC، دیگر نیازی به بازنویسی
computed
نخواهد بود و vue
میتواند مستقیماً از نسخهی @vue/reactivity
استفاده کند.🔗https://github.com/vuejs/rfcs/blob/master/active-rfcs/0041-reactivity-effect-scope.md
#️⃣#tip #vue
👥@IR_javascript_group
🆔@IR_javascript
GitHub
rfcs/active-rfcs/0041-reactivity-effect-scope.md at master · vuejs/rfcs
RFCs for substantial changes / feature additions to Vue core - vuejs/rfcs
درک تفاوتها: File در برابر Blob
گاهی اوقات در کد به موقعیتهایی برمیخوریم که بهدلیل درک نادرست از تفاوت میان Blob و File**، ابهاماتی بهوجود میآید. سپس این پرسشها مطرح میشوند:
«چرا نام فایل منتقل نمیشود؟»
«چرا تاریخ وجود ندارد؟»
یا «چطور میتوان این را بهدرستی با FormData ارسال کرد؟»
زمان آن رسیده که موضوع را روشن کنیم!
### Blob چیست؟
**Blob ساختاری دادهای است که یک شیء تغییرناپذیر شامل دادههای دودویی را نمایش میدهد.
نکات مهم:
- میتواند هر نوع دادهای را در خود جای دهد: تصویر، متن، ویدیو و ...
- اطلاعاتی دربارهی منبع فایل در خود ندارد؛
- فاقد نام (name) و تاریخ آخرین تغییر (lastModified) است؛
- اما میتوان به اندازه (size) و نوع (type) آن دسترسی داشت.
کاربردهای رایج Blob:
- تولید فایلها بهصورت «لحظهای» (مثلاً تولید فایل CSV یا JSON از رابط کاربری)
- ایجاد URL با استفاده از
- نگهداری موقت دادهها در حافظه
جمعبندی:
Blob روشی عمومی و انعطافپذیر برای نمایش هرگونه دادهی «خام» در یک وباپلیکیشن است.
در بسیاری از عملیات مربوط به محتوای دودویی در وب، پایه و اساس را Blob تشکیل میدهد.
---
### File چیست؟
File در واقع نسخهی توسعهیافتهی Blob به همراه فراداده (metadata) است.
نکات مهم:
- از Blob ارثبری میکند؛ یعنی تمام قابلیتهای Blob را داراست؛
- افزودههایی دارد مانند:
- شیء File همان چیزی است که هنگام انتخاب فایل توسط کاربر از طریق
کاربردهای رایج File:
- مدیریت فایلهایی که کاربر در اختیار برنامه قرار میدهد؛
- خواندن محتوای فایل با FileReader
- ارسال فایل به سرور
- پیشنمایش فایل در مرورگر
---
### نتیجهگیری نهایی:
🔹 اگر فقط به یک جریان دادهی دودویی نیاز دارید: Blob را انتخاب کنید.
🔹 اگر نیاز به شیئی دارید که همانند یک فایل رفتار کند: File انتخاب بهتری است.
و همین!
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
گاهی اوقات در کد به موقعیتهایی برمیخوریم که بهدلیل درک نادرست از تفاوت میان Blob و File**، ابهاماتی بهوجود میآید. سپس این پرسشها مطرح میشوند:
«چرا نام فایل منتقل نمیشود؟»
«چرا تاریخ وجود ندارد؟»
یا «چطور میتوان این را بهدرستی با FormData ارسال کرد؟»
زمان آن رسیده که موضوع را روشن کنیم!
### Blob چیست؟
**Blob ساختاری دادهای است که یک شیء تغییرناپذیر شامل دادههای دودویی را نمایش میدهد.
const blob = new Blob(["Hello, world!"], { type: "text/plain" });
نکات مهم:
- میتواند هر نوع دادهای را در خود جای دهد: تصویر، متن، ویدیو و ...
- اطلاعاتی دربارهی منبع فایل در خود ندارد؛
- فاقد نام (name) و تاریخ آخرین تغییر (lastModified) است؛
- اما میتوان به اندازه (size) و نوع (type) آن دسترسی داشت.
کاربردهای رایج Blob:
- تولید فایلها بهصورت «لحظهای» (مثلاً تولید فایل CSV یا JSON از رابط کاربری)
- ایجاد URL با استفاده از
URL.createObjectURL()
- نگهداری موقت دادهها در حافظه
جمعبندی:
Blob روشی عمومی و انعطافپذیر برای نمایش هرگونه دادهی «خام» در یک وباپلیکیشن است.
در بسیاری از عملیات مربوط به محتوای دودویی در وب، پایه و اساس را Blob تشکیل میدهد.
---
### File چیست؟
File در واقع نسخهی توسعهیافتهی Blob به همراه فراداده (metadata) است.
const file = new File(["Hello, world!"], "greeting.txt", {
type: "text/plain",
lastModified: Date.now()
});
نکات مهم:
- از Blob ارثبری میکند؛ یعنی تمام قابلیتهای Blob را داراست؛
- افزودههایی دارد مانند:
name
و lastModified
; - شیء File همان چیزی است که هنگام انتخاب فایل توسط کاربر از طریق
<input type="file">
بهدست میآید.کاربردهای رایج File:
- مدیریت فایلهایی که کاربر در اختیار برنامه قرار میدهد؛
- خواندن محتوای فایل با FileReader
- ارسال فایل به سرور
- پیشنمایش فایل در مرورگر
---
### نتیجهگیری نهایی:
🔹 اگر فقط به یک جریان دادهی دودویی نیاز دارید: Blob را انتخاب کنید.
🔹 اگر نیاز به شیئی دارید که همانند یک فایل رفتار کند: File انتخاب بهتری است.
و همین!
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
👍2
مهاجرت مایکروسافت به موتور کرومیوم یک تصمیم بسیار هوشمندانه بود.
در آغوش بگیر، توسعه بده، و حذف کن — راهبردی که هنوز هم کار میکند.
#️⃣#tool
👥@IR_javascript_group
🆔@IR_javascript
در آغوش بگیر، توسعه بده، و حذف کن — راهبردی که هنوز هم کار میکند.
#️⃣#tool
👥@IR_javascript_group
🆔@IR_javascript
عبارت «در آغوش بگیر، گسترش بده و نابود کن» (Embrace, Extend, and Extinguish – EEE) عبارتی است که، بنا بر گزارش وزارت دادگستری ایالات متحده، مایکروسافت در داخل شرکت برای توصیف راهبرد خود به کار میبرد. این استراتژی به این صورت عمل میکرد که ابتدا وارد حوزههایی با استانداردهای رایج و پرکاربرد میشد، سپس آن استانداردها را با قابلیتهای اختصاصی خود گسترش میداد، و در نهایت از این تفاوتها برای به حاشیه راندن و تضعیف جدی رقبا استفاده میکرد.
فرآیند «در آغوشگیری و گسترش» مایکروسافت در حوزه توسعه نرمافزار بهوضوح قابل مشاهده است:
از Visual Studio Code و تملک GitHub و npmjs.org گرفته تا معرفی TypeScript، و اکنون Copilot (محصولی بر پایه هوش مصنوعی OpenAI).
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
فرآیند «در آغوشگیری و گسترش» مایکروسافت در حوزه توسعه نرمافزار بهوضوح قابل مشاهده است:
از Visual Studio Code و تملک GitHub و npmjs.org گرفته تا معرفی TypeScript، و اکنون Copilot (محصولی بر پایه هوش مصنوعی OpenAI).
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
👍2
روندهای تاریخی در آمار استفاده از کتابخانههای جاوااسکریپت در وبسایتها
این گزارش، روندهای تاریخی مربوط به میزان استفاده از برترین کتابخانههای جاوااسکریپت را از آوریل سال دوهزار و بیستوچهار تا به امروز بررسی میکند.
🔗https://w3techs.com/technologies/history_overview/javascript_library/all
#️⃣#tool
👥@IR_javascript_group
🆔@IR_javascript
این گزارش، روندهای تاریخی مربوط به میزان استفاده از برترین کتابخانههای جاوااسکریپت را از آوریل سال دوهزار و بیستوچهار تا به امروز بررسی میکند.
🔗https://w3techs.com/technologies/history_overview/javascript_library/all
#️⃣#tool
👥@IR_javascript_group
🆔@IR_javascript
دسترسپذیری وبسایت و Screen Reader
این موضوعیست که انگار همه با آن آشنایی دارند، اما کمتر کسی آن را واقعاً درک میکند.
در توسعهی فرانتاند، معمولاً تمرکز ما بر ظاهر، عملکرد و تعاملپذیری است. اما دسترسپذیری چطور؟ معمولاً به آن میگوییم: «باشه، بعداً اضافهاش میکنیم.» تصور میشود که این فقط مربوط به موقعیتهای خاص و کاربران «خاص» است. اما واقعیت این است که دسترسپذیری برای آدمهای عادیست**—تنها با ابزارها و شرایط متفاوتی برای تعامل با رابط کاربری.
Screen reader ظاهر را نمیبیند؛ **ساختار را میخواند.
او «نمیبیند» که یک دکمه زیباست، بلکه تنها میفهمد این عنصر چیست (دکمه، بلوک، عنوان و غیره)، کجای ساختار DOM قرار گرفته (که در اولویت خواندن اثر دارد)، و آیا میتوان با آن تعامل داشت یا نه (مثل دکمهها، فیلدهای ورودی و موارد دیگر).
براساس همین اطلاعات، Screen reader تصمیم میگیرد که آیا لازم است این عنصر را برای کاربر بخواند یا نه.
---
### از پایه شروع کنیم:
چه چیزهایی لازم است تا چنین شیوهی تعامل با رابط، در سایت قابل استفاده باشد؟
#### ✅ استفاده از تگهای معنایی درست
تگهایی مانند:
اینها صرفاً «استانداردهای رایج» نیستند؛ بلکه زبانی هستند که اسکرینریدرها و APIهای دسترسپذیری از طریق آن با رابط کاربر ارتباط برقرار میکنند.
#### 🖼 متن جایگزین برای تصاویر
اگر تصویر حاوی معناست، همیشه ویژگی
اگر تصویر صرفاً تزئینی است،
#### ⌨️ فوکوس درست و ناوبری با کیبورد
با کلید Tab در وبسایت حرکت کن.
آیا ترتیب منطقی دارد؟
آیا تمام عناصر قابل فوکوس هستند؟
آیا «تله»ای وجود دارد که کاربر در آن گیر کند؟
اگر کاربر نتواند به یک دکمه برسد یا در ترتیب بین عناصر گم شود، این خود یک مانع است.
#### 🧠 استفاده هوشمندانه از ویژگیهای
هر جا امکان استفاده از تگ های معنایی بومی HTML وجود دارد، از آن استفاده کن.
ویژگیهایی مانند
اما اگر بدون دلیل موجه، از آنها استفاده کنی، فقط کد را سنگینتر و تجربهی کاربر را مختل خواهی کرد.
---
### نکتهی کلیدی:
دسترسپذیری «مخصوص دیگران» نیست.
این نه یک پیچیدگیست، نه باری اضافی؛ بلکه بخشی از همان توجهیست که به طراحی واکنشگرا، مسیر ناوبری واضح یا سرعت بارگذاری میدهی.
دسترسپذیری، فقط یک روش متفاوت و جایگزین برای تعامل با رابط کاربری توست.
و جالب اینجاست که دسترسپذیری معمولاً از سادهترین جا آغاز میشود:
نه با افزونههای پیشرفته یا ترفندهای پیچیده، بلکه با کدنویسی تمیز، شفاف، و دغدغهمندی برای کاربران واقعی.
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
این موضوعیست که انگار همه با آن آشنایی دارند، اما کمتر کسی آن را واقعاً درک میکند.
در توسعهی فرانتاند، معمولاً تمرکز ما بر ظاهر، عملکرد و تعاملپذیری است. اما دسترسپذیری چطور؟ معمولاً به آن میگوییم: «باشه، بعداً اضافهاش میکنیم.» تصور میشود که این فقط مربوط به موقعیتهای خاص و کاربران «خاص» است. اما واقعیت این است که دسترسپذیری برای آدمهای عادیست**—تنها با ابزارها و شرایط متفاوتی برای تعامل با رابط کاربری.
Screen reader ظاهر را نمیبیند؛ **ساختار را میخواند.
او «نمیبیند» که یک دکمه زیباست، بلکه تنها میفهمد این عنصر چیست (دکمه، بلوک، عنوان و غیره)، کجای ساختار DOM قرار گرفته (که در اولویت خواندن اثر دارد)، و آیا میتوان با آن تعامل داشت یا نه (مثل دکمهها، فیلدهای ورودی و موارد دیگر).
براساس همین اطلاعات، Screen reader تصمیم میگیرد که آیا لازم است این عنصر را برای کاربر بخواند یا نه.
---
### از پایه شروع کنیم:
چه چیزهایی لازم است تا چنین شیوهی تعامل با رابط، در سایت قابل استفاده باشد؟
#### ✅ استفاده از تگهای معنایی درست
تگهایی مانند:
button`، `nav`، `main`، `label`، `form
اینها صرفاً «استانداردهای رایج» نیستند؛ بلکه زبانی هستند که اسکرینریدرها و APIهای دسترسپذیری از طریق آن با رابط کاربر ارتباط برقرار میکنند.
#### 🖼 متن جایگزین برای تصاویر
اگر تصویر حاوی معناست، همیشه ویژگی
alt
را با توضیح مناسب قرار بده. اگر تصویر صرفاً تزئینی است،
alt=""
را تنظیم کن تا screen reader آن را نادیده بگیرد.#### ⌨️ فوکوس درست و ناوبری با کیبورد
با کلید Tab در وبسایت حرکت کن.
آیا ترتیب منطقی دارد؟
آیا تمام عناصر قابل فوکوس هستند؟
آیا «تله»ای وجود دارد که کاربر در آن گیر کند؟
اگر کاربر نتواند به یک دکمه برسد یا در ترتیب بین عناصر گم شود، این خود یک مانع است.
#### 🧠 استفاده هوشمندانه از ویژگیهای
aria-*
هر جا امکان استفاده از تگ های معنایی بومی HTML وجود دارد، از آن استفاده کن.
ویژگیهایی مانند
aria-label`، `aria-hidden`، `aria-live
و ... زمانی کاربرد دارند که HTML نتواند نیاز مورد نظر را برآورده کند. اما اگر بدون دلیل موجه، از آنها استفاده کنی، فقط کد را سنگینتر و تجربهی کاربر را مختل خواهی کرد.
---
### نکتهی کلیدی:
دسترسپذیری «مخصوص دیگران» نیست.
این نه یک پیچیدگیست، نه باری اضافی؛ بلکه بخشی از همان توجهیست که به طراحی واکنشگرا، مسیر ناوبری واضح یا سرعت بارگذاری میدهی.
دسترسپذیری، فقط یک روش متفاوت و جایگزین برای تعامل با رابط کاربری توست.
و جالب اینجاست که دسترسپذیری معمولاً از سادهترین جا آغاز میشود:
نه با افزونههای پیشرفته یا ترفندهای پیچیده، بلکه با کدنویسی تمیز، شفاف، و دغدغهمندی برای کاربران واقعی.
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
❤1
کوئریهای کانتینری (Container Queries) ابزاری در CSS هستند که این امکان را فراهم میکنند تا عناصر بر اساس ابعاد کانتینر والد خود استایلدهی شوند، نه صرفاً بر اساس اندازهی کل پنجرهی مرورگر.
در نسخهی کروم صد و سی و سه**، قابلیت جدیدی با عنوان **وضعیتهای اسکرول (Scroll States) برای کوئریهای کانتینری معرفی شده است که کنترل بیشتری بر رفتار عناصر در هنگام اسکرول فراهم میکند.
---
### وضعیتهای اسکرول (Scroll States) چیست؟
سه وضعیت جدید برای ویژگی
scrollable**، **stuck و snapped
این وضعیتها میتوانند در داخل قانون
---
### نمونه کد:
---
### موارد کاربرد:
- نمایش وضعیت اسکرول
بهصورت بصری به کاربر نشان دهید که هنوز محتوای بیشتری در پایین وجود دارد.
- تیترهای چسبنده (Sticky Headers)
بهطور خودکار، تیترها هنگام اسکرول در جای خود ثابت شوند.
- تغییر رفتار ناوبری
مثلاً نمایش دکمهی «بازگشت به بالا» تنها در صورتی که کاربر اسکرول کرده باشد.
- بهینهسازی رابط کاربری
پنهانسازی عناصر کماهمیت هنگام اسکرول برای افزایش تمرکز و فضای قابل مشاهده.
---
برای اطلاعات بیشتر، به مستندات رسمی CSS Container Queries مراجعه کنید.
این قابلیت جدید، گامی مهم بهسوی طراحی رابطهای کاربری هوشمندتر و پاسخگوتر به شرایط واقعی نمایش است.
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
در نسخهی کروم صد و سی و سه**، قابلیت جدیدی با عنوان **وضعیتهای اسکرول (Scroll States) برای کوئریهای کانتینری معرفی شده است که کنترل بیشتری بر رفتار عناصر در هنگام اسکرول فراهم میکند.
---
### وضعیتهای اسکرول (Scroll States) چیست؟
سه وضعیت جدید برای ویژگی
scroll-state
تعریف شدهاند: scrollable**، **stuck و snapped
این وضعیتها میتوانند در داخل قانون
@container
مورد استفاده قرار گیرند تا بسته به وضعیت اسکرول کانتینر، استایلهای خاصی اعمال شوند.---
### نمونه کد:
.stuck-top {
container-type: scroll-state;
position: sticky;
top: 0px;
nav {
@container scroll-state(stuck: top) {
background: Highlight;
color: HighlightText;
}
}
}
---
### موارد کاربرد:
- نمایش وضعیت اسکرول
بهصورت بصری به کاربر نشان دهید که هنوز محتوای بیشتری در پایین وجود دارد.
- تیترهای چسبنده (Sticky Headers)
بهطور خودکار، تیترها هنگام اسکرول در جای خود ثابت شوند.
- تغییر رفتار ناوبری
مثلاً نمایش دکمهی «بازگشت به بالا» تنها در صورتی که کاربر اسکرول کرده باشد.
- بهینهسازی رابط کاربری
پنهانسازی عناصر کماهمیت هنگام اسکرول برای افزایش تمرکز و فضای قابل مشاهده.
---
برای اطلاعات بیشتر، به مستندات رسمی CSS Container Queries مراجعه کنید.
این قابلیت جدید، گامی مهم بهسوی طراحی رابطهای کاربری هوشمندتر و پاسخگوتر به شرایط واقعی نمایش است.
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
👍2👏1
اگر در یک اپلیکیشن چندین تابع غیرهمزمان (مانند بارگذاری دادهها از بکاند) بهطور همزمان اجرا میشود و نیاز به نمایش یک انیمیشن پیشلودر واحد داریم، میتوانیم بهراحتی این کار را از طریق یک تابع composable پیادهسازی کنیم:
---
### AppLoader.vue
### useAppLoader.ts
### SomeComponent
---
این مثال از
برای نسخههای قدیمیتر Vue، میتوان از هر تابعی برای تولید یک شناسهی منحصر به فرد استفاده کرد.
#️⃣#tip #vue
👥@IR_javascript_group
🆔@IR_javascript
---
### AppLoader.vue
<script setup>
import { useAppLoader } from "@/app/composables/useAppLoader";
const { loading } = useAppLoader();
</script>
<template>
<div class="loader" :class="{ active: loading }">
<div class="loaderBar" />
</div>
</template>
### useAppLoader.ts
import { computed, reactive, ref } from "vue";
const loaderSet = reactive(new Set<string>());
const loading = computed(() => loaderSet.size > 0);
export function useAppLoader(id) {
function startLoading() {
loaderSet.add(id);
}
function stopLoading() {
loaderSet.delete(id);
}
return { loading, startLoading, stopLoading };
}
### SomeComponent
import { useId } from "Vue";
import { useAppLoader } from "@/app/composables/useAppLoader";
const { startLoading, stopLoading } = useAppLoader(useId());
startLoading();
product.value = await api.products.product(props.productId);
stopLoading();
---
این مثال از
useId
استفاده میکند که در Vue 3.5 معرفی شده است. برای نسخههای قدیمیتر Vue، میتوان از هر تابعی برای تولید یک شناسهی منحصر به فرد استفاده کرد.
#️⃣#tip #vue
👥@IR_javascript_group
🆔@IR_javascript
👍1
راحت ترین معماری برای یک برنامه مبتنی بر Vue 3، معماری ماژولار (ماژولمحور) است.
در این رویکرد، ساختار برنامه از همان ابتدا به ماژولهای منطقی و مستقل با وابستگی حداقلی تقسیم میشود. برای مثال، در یک فروشگاه آنلاین، میتوان ماژولهایی مانند:
- ماژول کاتالوگ محصولات
- ماژول صفحه محصول
- ماژول حساب کاربری / پنل شخصی کاربر
را تعریف کرد.
علاوه بر اینها، یک ماژول پوسته (App Shell) نیز وجود دارد؛ بخشی که ساختار کلی برنامه را شامل میشود، نظیر: هدر، فوتر، منوی کناری و ناحیه اصلی نمایش محتوا. بهتر است منابع عمومی و پرکاربرد مانند:
- متدهای API
- کتابخانه بینالمللیسازی
- کامپوننتهای پایهای نظیر
- توابع کمکی مانند
در این ماژول قرار گیرند.
---
هر ماژول، پوشهها و ساختار مستقل خود را دارد که معمولاً شامل بخشهای زیر است:
-
-
-
-
- و در صورت نیاز:
---
این جداسازی با وابستگی کم، این امکان را فراهم میکند که هر ماژول بهصورت **نسبتاً مستقل توسعه یابد**؛ که این موضوع در عمل موجب بهبود عملکرد تیم توسعه، سهولت نگهداری کد، و افزایش احتمال موفقیت پروژه میشود.
(ادامه دارد ... .)
#️⃣#tip #vue
👥@IR_javascript_group
🆔@IR_javascript
در این رویکرد، ساختار برنامه از همان ابتدا به ماژولهای منطقی و مستقل با وابستگی حداقلی تقسیم میشود. برای مثال، در یک فروشگاه آنلاین، میتوان ماژولهایی مانند:
- ماژول کاتالوگ محصولات
- ماژول صفحه محصول
- ماژول حساب کاربری / پنل شخصی کاربر
را تعریف کرد.
علاوه بر اینها، یک ماژول پوسته (App Shell) نیز وجود دارد؛ بخشی که ساختار کلی برنامه را شامل میشود، نظیر: هدر، فوتر، منوی کناری و ناحیه اصلی نمایش محتوا. بهتر است منابع عمومی و پرکاربرد مانند:
- متدهای API
- کتابخانه بینالمللیسازی
useI18n
- کامپوننتهای پایهای نظیر
BaseButton
- توابع کمکی مانند
stringHelpers
در این ماژول قرار گیرند.
---
هر ماژول، پوشهها و ساختار مستقل خود را دارد که معمولاً شامل بخشهای زیر است:
-
components
(کامپوننتها) -
composables
(توابع ترکیبی) -
assets
(منابع گرافیکی و استاتیک) -
utils
(توابع کمکی) - و در صورت نیاز:
api`، `routes`، `views`، `layouts
---
این جداسازی با وابستگی کم، این امکان را فراهم میکند که هر ماژول بهصورت **نسبتاً مستقل توسعه یابد**؛ که این موضوع در عمل موجب بهبود عملکرد تیم توسعه، سهولت نگهداری کد، و افزایش احتمال موفقیت پروژه میشود.
(ادامه دارد ... .)
#️⃣#tip #vue
👥@IR_javascript_group
🆔@IR_javascript
👍5🔥2👎1
### ساختار تخت (Flat)
زمانی که قصد راهاندازی یک پروژه کوچک Vue مانند یک «اثبات مفهوم» (Proof of Concept) را دارید، میتوانید ساختاری ساده و تخت برای پوشهها انتخاب کنید تا از پیچیدگیهای غیرضروری اجتناب شود:
---
### طراحی اتمی (Atomic Design)
برای اپلیکیشنهای بزرگ Vue، بهرهگیری از متدولوژی «طراحی اتمی» میتواند بسیار سودمند باشد. این روش، کامپوننتها را بهصورت سلسلهمراتبی از سادهترین تا پیچیدهترین دستهبندی میکند:
- اتمها: عناصر پایه مانند دکمهها و آیکونها
- مولکولها: گروهی از اتمها، مانند ورودی جستجو
- ارگانیسمها: کامپوننتهای پیچیدهتری مانند هدر یا کارتها
- قالبها (Templates): ساختار بصری صفحات
- صفحات (Pages): نمایش نهایی اطلاعات با دادههای واقعی
این روش موجب مقیاسپذیری بالا و قابلیت نگهداری بهتر پروژه میشود و انتقال از کامپوننتهای ساده به پیچیده را تسهیل میکند.
---
### طراحی ماژولار (Modular Design)
با گسترش پروژه، استفاده از معماری ماژولار توصیه میشود. در این رویکرد، هر قابلیت یا حوزه (Domain) بهصورت یک واحد مستقل تعریف میشود که نگهداری و توسعه آن آسانتر بوده و زمینهساز انتقال به معماریهای میکروسرویسی نیز هست.
---
### طراحی مبتنی بر ویژگیها (Feature-Sliced Design)
این روش برای پروژههای بزرگ و طولانیمدت طراحی شده است تا توسعه و نگهداری آنها را سادهتر و ساختارمندتر کند. در این مدل، اپلیکیشن به لایههایی با مسئولیتهای مشخص تقسیم میشود:
- app: تنظیمات کلی، استایلها و Providerها
- pages: صفحات کامل شامل دادهها
- widgets: بلاکهای مستقل رابط کاربری
- features: منطق عملکردی قابل استفاده مجدد
- entities: مدلهای اصلی کسبوکار مانند کاربر یا محصول
- shared: کامپوننتها و ابزارهای عمومی مانند UIKit یا API
---
### میکروفرانتاندها (Microfrontends)
میکروفرانتاندها مفهومی برگرفته از معماری میکروسرویسها هستند که در بخش فرانتاند پیادهسازی میشوند. این مدل به تیمها اجازه میدهد بخشهای مختلف رابط کاربری را بهصورت مستقل توسعه و منتشر کنند.
- پوسته برنامه: کنترل ساختار کلی و مسیرها
- رابطهای خردشده: هر بخش از برنامه بهطور مستقل پیادهسازی شده و میتواند با فناوری متفاوتی توسعه یابد.
مزیت اصلی این رویکرد، افزایش سرعت توسعه از طریق انتشار مستقل بخشهاست، هرچند پیادهسازی آن نیازمند هماهنگی بیشتر بین تیمها و زیرساخت پیچیدهتر است.
🔗https://vue-faq.org/ru/development/architectural-patterns.html?t=7
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
زمانی که قصد راهاندازی یک پروژه کوچک Vue مانند یک «اثبات مفهوم» (Proof of Concept) را دارید، میتوانید ساختاری ساده و تخت برای پوشهها انتخاب کنید تا از پیچیدگیهای غیرضروری اجتناب شود:
/src
|-- /components
| |-- BaseButton.vue
| |-- BaseCard.vue
| |-- PokemonList.vue
| |-- PokemonCard.vue
|-- /composables
| |-- usePokemon.js
|-- /utils
| |-- validators.js
|-- /layout
| |-- DefaultLayout.vue
| |-- AdminLayout.vue
|-- /plugins
| |-- translate.js
|-- /views
| |-- Home.vue
| |-- PokemonDetail.vue
|-- /router
| |-- index.js
|-- /store
| |-- index.js
|-- /assets
| |-- /images
| |-- /styles
|-- /tests
| |-- ...
|-- App.vue
|-- main.js
---
### طراحی اتمی (Atomic Design)
برای اپلیکیشنهای بزرگ Vue، بهرهگیری از متدولوژی «طراحی اتمی» میتواند بسیار سودمند باشد. این روش، کامپوننتها را بهصورت سلسلهمراتبی از سادهترین تا پیچیدهترین دستهبندی میکند:
- اتمها: عناصر پایه مانند دکمهها و آیکونها
- مولکولها: گروهی از اتمها، مانند ورودی جستجو
- ارگانیسمها: کامپوننتهای پیچیدهتری مانند هدر یا کارتها
- قالبها (Templates): ساختار بصری صفحات
- صفحات (Pages): نمایش نهایی اطلاعات با دادههای واقعی
این روش موجب مقیاسپذیری بالا و قابلیت نگهداری بهتر پروژه میشود و انتقال از کامپوننتهای ساده به پیچیده را تسهیل میکند.
/src
|-- /components
| |-- /atoms
| | |-- AtomButton.vue
| | |-- AtomIcon.vue
| |-- /molecules
| | |-- MoleculeSearchInput.vue
| | |-- MoleculePokemonThumbnail.vue
| |-- /organisms
| | |-- OrganismPokemonCard.vue
| | |-- OrganismHeader.vue
| |-- /templates
| | |-- TemplatePokemonList.vue
| | |-- TemplatePokemonDetail.vue
|-- /pages
| |-- PageHome.vue
| |-- PagePokemonDetail.vue
...
---
### طراحی ماژولار (Modular Design)
با گسترش پروژه، استفاده از معماری ماژولار توصیه میشود. در این رویکرد، هر قابلیت یا حوزه (Domain) بهصورت یک واحد مستقل تعریف میشود که نگهداری و توسعه آن آسانتر بوده و زمینهساز انتقال به معماریهای میکروسرویسی نیز هست.
/src
|-- /core
| |-- /components
| | |-- BaseButton.vue
| |-- /models
| |-- /store
| |-- /services
| |-- /views
|-- /modules
| |-- /pokemon
| | |-- /components
| | |-- /models
| | |-- /store
| | |-- /services
| | |-- /views
| | |-- /tests
| |-- /search
| |-- ...
...
---
### طراحی مبتنی بر ویژگیها (Feature-Sliced Design)
این روش برای پروژههای بزرگ و طولانیمدت طراحی شده است تا توسعه و نگهداری آنها را سادهتر و ساختارمندتر کند. در این مدل، اپلیکیشن به لایههایی با مسئولیتهای مشخص تقسیم میشود:
- app: تنظیمات کلی، استایلها و Providerها
- pages: صفحات کامل شامل دادهها
- widgets: بلاکهای مستقل رابط کاربری
- features: منطق عملکردی قابل استفاده مجدد
- entities: مدلهای اصلی کسبوکار مانند کاربر یا محصول
- shared: کامپوننتها و ابزارهای عمومی مانند UIKit یا API
/src
|-- /app
|-- /pages
|-- /widgets
|-- /features
|-- /entities
|-- /shared
...
---
### میکروفرانتاندها (Microfrontends)
میکروفرانتاندها مفهومی برگرفته از معماری میکروسرویسها هستند که در بخش فرانتاند پیادهسازی میشوند. این مدل به تیمها اجازه میدهد بخشهای مختلف رابط کاربری را بهصورت مستقل توسعه و منتشر کنند.
- پوسته برنامه: کنترل ساختار کلی و مسیرها
- رابطهای خردشده: هر بخش از برنامه بهطور مستقل پیادهسازی شده و میتواند با فناوری متفاوتی توسعه یابد.
مزیت اصلی این رویکرد، افزایش سرعت توسعه از طریق انتشار مستقل بخشهاست، هرچند پیادهسازی آن نیازمند هماهنگی بیشتر بین تیمها و زیرساخت پیچیدهتر است.
🔗https://vue-faq.org/ru/development/architectural-patterns.html?t=7
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
Vue FAQ
Архитектурные решения | Vue FAQ
Vue FAQ - information about Vue.js and frontend development in general
👍2
در انتخاب کتابخانهی رابط کاربری (UI Library) مناسب برای پروژههای Vue 3 یا Nuxt 3، باید عواملی مانند قابلیت توسعه، مستندات، پشتیبانی از TailwindCSS، پشتیبانی از SSR (در Nuxt)، و تجربه کاربری را در نظر بگیرید
کتالوگ کتابخانههای رابط کاربری برای vue , nuxt
🔗 https://ui-libs.vercel.app/
#️⃣#tool
👥@IR_javascript_group
🆔@IR_javascript
کتالوگ کتابخانههای رابط کاربری برای vue , nuxt
🔗 https://ui-libs.vercel.app/
#️⃣#tool
👥@IR_javascript_group
🆔@IR_javascript
👏3👍1
لیستی از سایت هایی که در آنها می توانید آموزش های رایگان پیدا کنید
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/
https://www.apps4all.com/
https://oneddl.org/
https://sanet.st/
https://badshahuploads.xyz/
https://www.scenep2p.com/?do=search
https://www.downduck.com/
https://0dayhome.net/
https://dl4all.org/
https://downturk.net/
https://www.youku.com/ku/webhome
https://rutube.ru/
https://dzen.ru/
https://www.aparat.com/
https://git.ir/
https://udemyiran.com/
اگر مورد دیگری را میشناسید در بخش نظرات مطرح کنید
#️⃣#tool
👥@IR_javascript_group
🆔@IR_javascript
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/
https://www.apps4all.com/
https://oneddl.org/
https://sanet.st/
https://badshahuploads.xyz/
https://www.scenep2p.com/?do=search
https://www.downduck.com/
https://0dayhome.net/
https://dl4all.org/
https://downturk.net/
https://www.youku.com/ku/webhome
https://rutube.ru/
https://dzen.ru/
https://www.aparat.com/
https://git.ir/
https://udemyiran.com/
اگر مورد دیگری را میشناسید در بخش نظرات مطرح کنید
#️⃣#tool
👥@IR_javascript_group
🆔@IR_javascript
Bilibili
哔哩哔哩 (゜-゜)つロ 干杯~-bilibili
哔哩哔哩(bilibili.com)是国内知名的视频弹幕网站,这里有及时的动漫新番,活跃的ACG氛围,有创意的Up主。大家可以在这里找到许多欢乐。
🔥3👍2
در این مطلب میخواهیم درباره دو هوک کاربردی در 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