ایجاد اپلیکیشنهای وب دسترسپذیر با Vue
یک کتابخانه متنباز شامل کامپوننتهای خام و بدون استایل که همراه با نمونههای متنوع و کاربردهای آماده ارائه میشود و میتوان آن را مستقیماً در پروژههای شما ادغام کرد.
🔗https://reka-ui.com/
#️⃣#npm_module
👥@IR_javascript_group
🆔@IR_javascript
یک کتابخانه متنباز شامل کامپوننتهای خام و بدون استایل که همراه با نمونههای متنوع و کاربردهای آماده ارائه میشود و میتوان آن را مستقیماً در پروژههای شما ادغام کرد.
🔗https://reka-ui.com/
#️⃣#npm_module
👥@IR_javascript_group
🆔@IR_javascript
👍2
ساختهشده توسط هوش مصنوعی با Three.js
کدنویسی وایب (Vibe Coding یا Vibecoding) یک تکنیک برنامهنویسی وابسته به هوش مصنوعی است که در آن، فرد مسئله را در چند جمله بهعنوان یک پرومت برای یک مدل زبانی بزرگ (LLM) آموزشدیده در زمینهی کدنویسی توصیف میکند. سپس، LLM کد نرمافزار را تولید میکند و نقش برنامهنویس از کدنویسی دستی به هدایت، آزمایش و اصلاح کد تولیدشده توسط هوش مصنوعی تغییر مییابد.
حامیان این روش معتقدند که Vibe Coding به برنامهنویسان آماتور اجازه میدهد بدون نیاز به آموزش و مهارتهای عمیق مهندسی نرمافزار، نرمافزار تولید کنند.
🎮 هماکنون بازی کنید:
summer-afternoon.vlucendo.com
🔗https://t.me/HamidrezaKaramianOfficial/2254
#️⃣#tool
👥@IR_javascript_group
🆔@IR_javascript
کدنویسی وایب (Vibe Coding یا Vibecoding) یک تکنیک برنامهنویسی وابسته به هوش مصنوعی است که در آن، فرد مسئله را در چند جمله بهعنوان یک پرومت برای یک مدل زبانی بزرگ (LLM) آموزشدیده در زمینهی کدنویسی توصیف میکند. سپس، LLM کد نرمافزار را تولید میکند و نقش برنامهنویس از کدنویسی دستی به هدایت، آزمایش و اصلاح کد تولیدشده توسط هوش مصنوعی تغییر مییابد.
حامیان این روش معتقدند که Vibe Coding به برنامهنویسان آماتور اجازه میدهد بدون نیاز به آموزش و مهارتهای عمیق مهندسی نرمافزار، نرمافزار تولید کنند.
🎮 هماکنون بازی کنید:
summer-afternoon.vlucendo.com
🔗https://t.me/HamidrezaKaramianOfficial/2254
#️⃣#tool
👥@IR_javascript_group
🆔@IR_javascript
👍2
معرفی Motion برای Vue
Motion یک کتابخانهی محبوب و قدرتمند برای انیمیشن است که بیشتر با React شناخته میشود، اما اکنون نسخهی Vue آن نیز عرضه شده و کاملاً مجهز به تمام ویژگیها است.
🔗https://motion.dev/docs/vue
#️⃣#npm_module
👥@IR_javascript_group
🆔@IR_javascript
Motion یک کتابخانهی محبوب و قدرتمند برای انیمیشن است که بیشتر با React شناخته میشود، اما اکنون نسخهی Vue آن نیز عرضه شده و کاملاً مجهز به تمام ویژگیها است.
🔗https://motion.dev/docs/vue
#️⃣#npm_module
👥@IR_javascript_group
🆔@IR_javascript
👍3
اگر یک آرایه دارید که هر عنصر آن شامل یک مقدار computed است، بهتر است یک مقدار computed برای کل آرایه ایجاد کنید تا اینکه برای هر عنصر جداگانه یک مقدار computed داشته باشید.
### نمونه نامناسب
### نمونه بهینه
با این روش، محاسبات بهینهتر انجام میشود و از ایجاد چندین مقدار computed غیرضروری جلوگیری خواهد شد.
#️⃣#tip #vue
👥@IR_javascript_group
🆔@IR_javascript
### نمونه نامناسب
const rows = productRows.map(row => ({
...row,
total: computed(() => row.price * row.qty),
}));
### نمونه بهینه
const computedRows = computed(() =>
productRows.map(row => ({
...row,
total: row.price * row.qty,
}))
);
با این روش، محاسبات بهینهتر انجام میشود و از ایجاد چندین مقدار computed غیرضروری جلوگیری خواهد شد.
#️⃣#tip #vue
👥@IR_javascript_group
🆔@IR_javascript
👍1
سادهترین روش برای نمایش «دیروز» در هر زبانی، استفاده از Relative TimeFormat است!
یکی از ابزارهای موردعلاقه من برای کار با تاریخ، Intl.RelativeTimeFormat است. این ابزار به شما امکان میدهد زمان نسبی را بهصورت زیبا نمایش دهید، مانند: «۵ دقیقه پیش»، «دو روز بعد»، «فردا» — و همه این موارد بهطور خودکار با توجه به تنظیمات زبانی کاربر انجام میشود!
### مثال پایه
فرض کنید میخواهیم زمان انتشار یک پست را نمایش دهیم:
### پارامترهای کلیدی:
-
- `numeric: 'auto'
### پارامترهای متد `format`
✔️ آرگومان اول – عددی که مشخص میکند زمان چقدر از لحظهی فعلی فاصله دارد.
✔️ آرگومان دوم – واحد زمانی مانند
### چند نمونه دیگر:
حالا دیگر نیازی به نوشتن توابع دستی برای نمایش «۵ دقیقه پیش» ندارید! میتوانید بهسادگی از Intl.RelativeTimeFormat استفاده کنید.
نظر شما دربارهی این ابزار چیست؟ تا به حال در پروژههایتان از آن استفاده کردهاید؟
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
یکی از ابزارهای موردعلاقه من برای کار با تاریخ، Intl.RelativeTimeFormat است. این ابزار به شما امکان میدهد زمان نسبی را بهصورت زیبا نمایش دهید، مانند: «۵ دقیقه پیش»، «دو روز بعد»، «فردا» — و همه این موارد بهطور خودکار با توجه به تنظیمات زبانی کاربر انجام میشود!
### مثال پایه
فرض کنید میخواهیم زمان انتشار یک پست را نمایش دهیم:
const rtf = new Intl.RelativeTimeFormat('fa', { numeric: 'auto' });
console.log(rtf.format(-1, 'day')); // "دیروز"
console.log(rtf.format(2, 'week')); // "دو هفته بعد"
### پارامترهای کلیدی:
-
'fa'
– زبان موردنظر که میتوانید آن را به 'en'`،
'fr'،
'ja'` و ... تغییر دهید. - `numeric: 'auto'
– باعث میشود بهجای «۱ روز پیش»، عبارت «دیروز» نمایش داده شود. مقدار پیشفرض این گزینه
'always' است، که در این صورت `format(-1, 'day')
مقدار «۱ روز پیش» را برمیگرداند، نه «دیروز». ### پارامترهای متد `format`
✔️ آرگومان اول – عددی که مشخص میکند زمان چقدر از لحظهی فعلی فاصله دارد.
✔️ آرگومان دوم – واحد زمانی مانند
second`، `minute`، `hour`، `day`، `week`، `month`، `year
. ### چند نمونه دیگر:
console.log(rtf.format(-3, 'month')); // "سه ماه پیش"
console.log(rtf.format(1, 'year')); // "سال آینده"
حالا دیگر نیازی به نوشتن توابع دستی برای نمایش «۵ دقیقه پیش» ندارید! میتوانید بهسادگی از Intl.RelativeTimeFormat استفاده کنید.
نظر شما دربارهی این ابزار چیست؟ تا به حال در پروژههایتان از آن استفاده کردهاید؟
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
❤3🔥3
در هستهی Nuxt قابلیت هیدراسیون تنبل (Lazy Hydration) اضافه شده است—پس دیگر نیازی به ساخت راهکارهای سفارشی نیست! اما بیایید قدمبهقدم بررسی کنیم.
### 🚀 Vue 3.5 و ارتقای SSR
در Vue 3.5 SSR بهبود یافته و حالا کامپوننتهای غیرهمزمان (Async Components) میتوانند زمان هیدراته شدن خود را از طریق استراتژی hydrate در API `defineAsyncComponent()` کنترل کنند. مثلاً، میتوان تعیین کرد که یک کامپوننت فقط هنگام نمایش در صفحه هیدراته شود:
### 🔥 Nuxt 3.16 و پشتیبانی از Delayed Hydration
📅 در ۷ مارس ۲۰۲۵ نسخهی Nuxt 3.16 منتشر شد که شامل ویژگیهای جدید، بهبود عملکرد، ابزارهای توسعهی بهتر و... بود، اما مهمترین قابلیت اضافهشده، Delayed Hydration است. توسعهدهندگان Nuxt در وبلاگ خود جزئیات این قابلیت را توضیح دادهاند.
#### ✅ مثال: هیدراته شدن کامپوننت هنگام ورود به ویوپورت
✅ حالا کامپوننت فقط وقتی در زون دید کاربر قرار بگیرد، لود و اجرا میشود—دیگر نیازی به نوشتن اسکریپتهای پیچیده برای ردیابی و بارگذاری نیست.
🔹 همچنین میتوان از hook جدید `hydrated` برای اجرای دستورات خاص پس از هیدراته شدن کامپوننت استفاده کرد:
### 📌 چه خبر؟
🔹 این ویژگی تنظیمات مختلفی دارد که میتوانید نحوهی کارکرد آن را در مستندات Nuxt مطالعه کنید.
🔹 Nuxt بهسرعت در حال پیشرفت است و وقت آن رسیده که این قابلیت را در محیط Production تست کنیم.
🔹 شاید وقتش رسیده که کامپوننتهای سمت سرور (Server Components) را هم امتحان کنیم؟ (قابلیت آزمایشی nuxt-islands – اما این بحث را میگذاریم برای بعد 😉)
#️⃣#tip #vue
👥@IR_javascript_group
🆔@IR_javascript
### 🚀 Vue 3.5 و ارتقای SSR
در Vue 3.5 SSR بهبود یافته و حالا کامپوننتهای غیرهمزمان (Async Components) میتوانند زمان هیدراته شدن خود را از طریق استراتژی hydrate در API `defineAsyncComponent()` کنترل کنند. مثلاً، میتوان تعیین کرد که یک کامپوننت فقط هنگام نمایش در صفحه هیدراته شود:
import { defineAsyncComponent, hydrateOnVisible } from 'vue';
const AsyncComp = defineAsyncComponent({
loader: () => import('./Comp.vue'),
hydrate: hydrateOnVisible()
});
### 🔥 Nuxt 3.16 و پشتیبانی از Delayed Hydration
📅 در ۷ مارس ۲۰۲۵ نسخهی Nuxt 3.16 منتشر شد که شامل ویژگیهای جدید، بهبود عملکرد، ابزارهای توسعهی بهتر و... بود، اما مهمترین قابلیت اضافهشده، Delayed Hydration است. توسعهدهندگان Nuxt در وبلاگ خود جزئیات این قابلیت را توضیح دادهاند.
#### ✅ مثال: هیدراته شدن کامپوننت هنگام ورود به ویوپورت
<!-- کامپوننت تنها زمانی هیدراته میشود که در محدودهی دید کاربر قرار بگیرد -->
<LazyExpensiveComponent hydrate-on-visible />
✅ حالا کامپوننت فقط وقتی در زون دید کاربر قرار بگیرد، لود و اجرا میشود—دیگر نیازی به نوشتن اسکریپتهای پیچیده برای ردیابی و بارگذاری نیست.
🔹 همچنین میتوان از hook جدید `hydrated` برای اجرای دستورات خاص پس از هیدراته شدن کامپوننت استفاده کرد:
<LazyComponent hydrate-on-visible @hydrated="onComponentHydrated" />
### 📌 چه خبر؟
🔹 این ویژگی تنظیمات مختلفی دارد که میتوانید نحوهی کارکرد آن را در مستندات Nuxt مطالعه کنید.
🔹 Nuxt بهسرعت در حال پیشرفت است و وقت آن رسیده که این قابلیت را در محیط Production تست کنیم.
🔹 شاید وقتش رسیده که کامپوننتهای سمت سرور (Server Components) را هم امتحان کنیم؟ (قابلیت آزمایشی nuxt-islands – اما این بحث را میگذاریم برای بعد 😉)
#️⃣#tip #vue
👥@IR_javascript_group
🆔@IR_javascript
👍1
معمولاً برای گروهبندی یک آرایه بر اساس یک کلید خاص، از متد
اما اکنون متدهای جدیدی مانند
مثال در جاوااسکریپت:
این روش، کدی خواناتر و ساختیافتهتر ارائه میدهد و مناسبِ زمانیست که بخواهید دادهها را بر اساس یک ویژگی مشخص دستهبندی کنید، بدون نیاز به نوشتن منطق دستی در
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
reduce
استفاده میشود. اما اکنون متدهای جدیدی مانند
Object.groupBy
و Map.groupBy
در دسترس هستند که این فرآیند را بسیار سادهتر میکنند.مثال در جاوااسکریپت:
const users = [
{ id: ۱، name: "Alex"، role: "admin" },
{ id: ۲، name: "Anna"، role: "user" },
];
const grouped = Object.groupBy(users, ({ role }) => role);
// نتیجه:
// {
// admin: [{...}],
// user: [{...}]
// }
این روش، کدی خواناتر و ساختیافتهتر ارائه میدهد و مناسبِ زمانیست که بخواهید دادهها را بر اساس یک ویژگی مشخص دستهبندی کنید، بدون نیاز به نوشتن منطق دستی در
reduce
.#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
🔥5
This media is not supported in your browser
VIEW IN TELEGRAM
هستهی Jupyter برای javascript
Deno بهصورت پیشفرض همراه با یک هستهی Jupyter ارائه میشود که امکان نوشتن JavaScript و TypeScript را در محیطهای تعاملی نوتبوک فراهم میسازد. در این محیط میتوانید بهسادگی از APIهای وب و Deno استفاده کرده و حتی بستههای npm را مستقیماً در نوتبوک خود وارد (import) کنید.
🔗https://docs.deno.com/runtime/reference/cli/jupyter/
#️⃣#tool
👥@IR_javascript_group
🆔@IR_javascript
Deno بهصورت پیشفرض همراه با یک هستهی Jupyter ارائه میشود که امکان نوشتن JavaScript و TypeScript را در محیطهای تعاملی نوتبوک فراهم میسازد. در این محیط میتوانید بهسادگی از APIهای وب و Deno استفاده کرده و حتی بستههای npm را مستقیماً در نوتبوک خود وارد (import) کنید.
🔗https://docs.deno.com/runtime/reference/cli/jupyter/
#️⃣#tool
👥@IR_javascript_group
🆔@IR_javascript
🔥1
### چرا باید از استفاده کنترلنشده از
#### یک. برهم خوردن جریان واکنشی (Reactive Flow)
استفاده از
در ظاهر ساده است، اما وقتی همین کد در چند مؤلفه با دادههای مشابه یا اثرات جانبی دیگر تکرار شود، کنترل جریان دادهها سختتر شده و رفتار برنامه غیرقابل پیشبینی میشود.
Vue معماری واکنشگرای یکطرفه (از داده به UI) را ترویج میدهد، اما
#### دو. کاهش خوانایی و دشواری در نگهداری
وقتی در یک مؤلفه چندین
این نوع پراکندگی منطق در `watch`ها:
- خوانایی کد را پایین میآورد
- بازسازی (refactor) و انتقال منطق به composableها را دشوار میکند
در مقابل، میتوان این رفتارها را در یک computed مجتمع یا composable مشخص و مستقل تعریف کرد.
#### سه. تأثیر منفی بر عملکرد
مثلاً اگر یک شیء عمیق را با
اگر
ویژگیهای محاسبهشونده کش میشوند، سبکتر هستند و اجرای بهتری دارند.
#### چهار. خطر نشت حافظه (Memory Leak)
در مؤلفههایی که با شرط
و در
اگر این
---
### ✅ راهکار پیشنهادی
قبل از استفاده از `watch`، ابتدا این پرسش را از خودتان بپرسید:
> «آیا میتوان این مسئله را با `computed`، `props` یا
در بسیاری از موارد پاسخ *بله* است، و انتخاب راهحلهای اعلانی (declarative) باعث خوانایی، عملکرد بهتر و مدیریت سادهتر خواهد شد.
#️⃣#tip #vue
👥@IR_javascript_group
🆔@IR_javascript
watch
پرهیز کرد؟#### یک. برهم خوردن جریان واکنشی (Reactive Flow)
استفاده از
watch
گاهی باعث پنهان شدن منطق واکنشگرایی میشود. برای مثال:watch(() => userId.value, async (newId) => {
const data = await fetchUserData(newId);
userData.value = data;
});
در ظاهر ساده است، اما وقتی همین کد در چند مؤلفه با دادههای مشابه یا اثرات جانبی دیگر تکرار شود، کنترل جریان دادهها سختتر شده و رفتار برنامه غیرقابل پیشبینی میشود.
Vue معماری واکنشگرای یکطرفه (از داده به UI) را ترویج میدهد، اما
watch
اغلب برای تبدیل داده به داده استفاده میشود که جریان را پیچیده میکند و اشکالزدایی را دشوارتر میسازد.#### دو. کاهش خوانایی و دشواری در نگهداری
وقتی در یک مؤلفه چندین
watch
بهصورت زنجیرهای نوشته شوند، ساختار کد بهشکل کلاف سردرگمی درمیآید که فهم آن زمانبر است:watch(() => settings.value.theme, applyTheme);
watch(() => settings.value.language, loadTranslations);
watch(() => settings.value.notifications, updateNotifications);
این نوع پراکندگی منطق در `watch`ها:
- خوانایی کد را پایین میآورد
- بازسازی (refactor) و انتقال منطق به composableها را دشوار میکند
در مقابل، میتوان این رفتارها را در یک computed مجتمع یا composable مشخص و مستقل تعریف کرد.
#### سه. تأثیر منفی بر عملکرد
مثلاً اگر یک شیء عمیق را با
deep: true
مانیتور کنید:watch(settings, (newVal, oldVal) => {
// مقایسه عمیق کل ساختار
}, { deep: true });
اگر
settings
شامل اشیاء یا آرایههای بزرگ باشد، عملکرد برنامه افت خواهد کرد. از طرفی، بسیاری از کاربردهای watch
را میتوان با computed
حل کرد:const isDarkTheme = computed(() => settings.value.theme === 'dark');
ویژگیهای محاسبهشونده کش میشوند، سبکتر هستند و اجرای بهتری دارند.
#### چهار. خطر نشت حافظه (Memory Leak)
در مؤلفههایی که با شرط
v-if
نمایش داده میشوند، اگر watch
بدون مدیریت درست ایجاد شود:<template>
<div v-if="showComponent">
<SomeComponent />
</div>
</template>
و در
SomeComponent
بنویسیم:watch(async() => someReactiveValue.value, await doSomething);
اگر این
watch
هنگام نابودی مؤلفه (unmount) لغو نشود، بهمرور زمان منابع حافظه را اشغال کرده و باعث نشت حافظه میشود.---
### ✅ راهکار پیشنهادی
قبل از استفاده از `watch`، ابتدا این پرسش را از خودتان بپرسید:
> «آیا میتوان این مسئله را با `computed`، `props` یا
emit
حل کرد؟»در بسیاری از موارد پاسخ *بله* است، و انتخاب راهحلهای اعلانی (declarative) باعث خوانایی، عملکرد بهتر و مدیریت سادهتر خواهد شد.
#️⃣#tip #vue
👥@IR_javascript_group
🆔@IR_javascript
👍1
سایت pollinations.ai یکی از رابطهای برنامهنویسی (API) مناسب و ساده برای تولید تصاویر با استفاده از هوش مصنوعی است.
### مثال درخواست GET برای دریافت متن:
### نمونه استفاده در کد HTML:
در تصویر بالا، نمونهای از تولید تصویر توسط مدل DALL-E نسخهٔ سوم نمایش داده شده که از متن داخل بلاک کد (prompt) استفاده کرده است.
#️⃣#tool
👥@IR_javascript_group
🆔@IR_javascript
### مثال درخواست GET برای دریافت متن:
GET https://text.pollinations.ai/{prompt}
### نمونه استفاده در کد HTML:
<img
src="https://image.pollinations.ai/prompt/A%20modern%20and%20vibrant%20digital%20illustration%20of%20a%20Telegram%20channel%20called%20%22IR_javascript%22,%20focused%20on%20web%20development,%20JavaScript,%20and%20coding.%20The%20scene%20features%20glowing%20code%20snippets,%20stylized%20browser%20windows,%20Iranian%20cultural%20motifs%20subtly%20integrated%20into%20the%20design,%20and%20futuristic%20UI%20elements.%20The%20background%20includes%20icons%20of%20JavaScript%20(JS),%20HTML,%20and%20CSS,%20with%20a%20dark%20mode%20theme%20and%20a%20sleek%20techy%20look.%20Emphasize%20community,%20learning,%20and%20innovation.%20Perfect%20for%20a%20tech%20advertisement%20poster."
alt="تصویری زیبا"
/>
در تصویر بالا، نمونهای از تولید تصویر توسط مدل DALL-E نسخهٔ سوم نمایش داده شده که از متن داخل بلاک کد (prompt) استفاده کرده است.
#️⃣#tool
👥@IR_javascript_group
🆔@IR_javascript
🔥2
همهچیز دربارهی favicon
🔻 چرا این مقاله مهمه؟
چون ساخت آیکون برای سایت به یه کابوس تبدیل شده؛ بیش از ۲۰ فایل PNG با اندازههای مختلف فقط برای نمایش یه لوگوی ساده؟ واقعاً لازمه؟ نه!
### نسخهی بسیار خلاصه
بهجای ساخت دهها آیکون، کافیست تنها پنج آیکون و یک فایل JSON ایجاد کنیم.
کد HTML:
و فایل مانیفست وب:
همین و بس. اگر مایلید بدانید چطور به این نتیجه رسیدم، ادامهی مقاله را بخوانید.
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
🔻 چرا این مقاله مهمه؟
چون ساخت آیکون برای سایت به یه کابوس تبدیل شده؛ بیش از ۲۰ فایل PNG با اندازههای مختلف فقط برای نمایش یه لوگوی ساده؟ واقعاً لازمه؟ نه!
### نسخهی بسیار خلاصه
بهجای ساخت دهها آیکون، کافیست تنها پنج آیکون و یک فایل JSON ایجاد کنیم.
کد HTML:
<link rel="icon" href="/favicon.ico" sizes="any"><!-- سیودو در سیودو پیکسل -->
<link rel="icon" href="/icon.svg" type="image/svg+xml">
<link rel="apple-touch-icon" href="/apple-touch-icon.png"><!-- صد و هشتاد در صد و هشتاد پیکسل -->
<link rel="manifest" href="/manifest.webmanifest">
و فایل مانیفست وب:
// manifest.webmanifest
{
"icons": [
{ "src": "/icon-192.png", "type": "image/png", "sizes": "192x192" },
{ "src": "/icon-512.png", "type": "image/png", "sizes": "512x512" }
]
}
همین و بس. اگر مایلید بدانید چطور به این نتیجه رسیدم، ادامهی مقاله را بخوانید.
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
### مجموعه ایدهآل فاوآیکونها
بهجای ایجاد تصاویر متعدد با اندازههای مختلف، تصمیم گرفتم به SVG و قابلیت مقیاسپذیری مرورگر تکیه کنم. نگران عملکرد نباشید:
- مرورگرها فاوآیکونها را در پسزمینه بارگذاری میکنند، بنابراین اندازه بزرگ فایل فاوآیکون تأثیری بر عملکرد وبسایت ندارد
- SVG روشی عالی برای کاهش اندازه آیکونها برای تصاویری است که نباید بهصورت شطرنجی باشند؛ برای بسیاری از لوگوها، فایل نهایی بسیار کوچکتر از PNG خواهد بود.
با داشتن تنها سه فایل PNG، میتوان آنها را با دقت بیشتری بهینهسازی کرد و با استفاده از تنظیمات مناسب در ابزارهای پیشرفته، کیفیت را حفظ نمود. این کار مشکل کاربرانی را که برای هر مگابایت اینترنت هزینه میپردازند، حل میکند.
اکنون به مجموعه حداقلی که از تحقیقات و آزمایشهایم به دست آوردهام، میپردازیم. این فهرست باید با تمامی مرورگرها و دستگاههای محبوب، چه قدیمی و چه جدید، سازگار باشد
### favicon.ico برای مرورگرهای قدیمی
فایلهای ICO میتوانند چندین نسخه از تصویر با اندازههای مختلف را در خود جای دهند. توصیه میکنم از یک تصویر با اندازه ۳۲×۳۲ پیکسل استفاده کنید. نسخه ۱۶×۱۶ را تنها در صورتی ایجاد کنید که لوگو در این اندازه وضوح خود را از دست ندهد یا طراح شما بتواند آن را بهصورت دستی برای این اندازه بازطراحی کند.
بهتر است این فایل را در مسیر دقیق
برای رفع اشکال Chrome که بهجای SVG، فایل ICO را انتخاب میکند، به
### یک آیکون SVG با نسخههای روشن/تاریک برای مرورگرهای مدرن
SVG یک فرمت برداری است که بهجای پیکسلها، منحنیها را توصیف میکند. در اندازههای بزرگ، این روش کارآمدتر از تصاویر شطرنجی است. در زمان نگارش این مقاله، ۷۲٪ از مرورگرها از آیکونهای SVG پشتیبانی میکنند.
صفحه HTML شما باید دارای تگ
SVG یک فرمت XML است و میتواند تگ
### تصویر PNG با اندازه ۱۸۰×۱۸۰ برای دستگاههای اپل
آیکون Apple touch تصویری برای صفحه اصلی iPhone یا iPad است. در صفحه HTML شما باید تگی با
از iOS 8 به بعد، برای iPad به تصویری با رزولوشن ۱۸۰×۱۸۰ نیاز است. دستگاههای قدیمیتر آن را بهصورت خودکار مقیاسدهی میکنند.
نکتهای کوچک: آیکون Apple touch بهتر به نظر میرسد اگر حاشیهای به اندازه ۲۰ پیکسل داشته باشد و رنگ پسزمینهای اضافه شود. برای این کار میتوانید از هر ویرایشگر گرافیکی استفاده کنید.
### مانیفست وباپلیکیشن با آیکونهای PNG ۱۹۲×۱۹۲ و ۵۱۲×۵۱۲ برای دستگاههای اندروید
- مانیفست وباپلیکیشن یک فایل JSON است که تمامی جزئیات لازم برای نصب وبسایت شما بهعنوان یک اپلیکیشن سیستمی را فراهم میکند. این فرمت توسط گوگل در چارچوب ابتکار PWA معرفی شده است.
- صفحه HTML شما باید تگی با
- در مانیفست باید فیلد
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
بهجای ایجاد تصاویر متعدد با اندازههای مختلف، تصمیم گرفتم به SVG و قابلیت مقیاسپذیری مرورگر تکیه کنم. نگران عملکرد نباشید:
- مرورگرها فاوآیکونها را در پسزمینه بارگذاری میکنند، بنابراین اندازه بزرگ فایل فاوآیکون تأثیری بر عملکرد وبسایت ندارد
- SVG روشی عالی برای کاهش اندازه آیکونها برای تصاویری است که نباید بهصورت شطرنجی باشند؛ برای بسیاری از لوگوها، فایل نهایی بسیار کوچکتر از PNG خواهد بود.
با داشتن تنها سه فایل PNG، میتوان آنها را با دقت بیشتری بهینهسازی کرد و با استفاده از تنظیمات مناسب در ابزارهای پیشرفته، کیفیت را حفظ نمود. این کار مشکل کاربرانی را که برای هر مگابایت اینترنت هزینه میپردازند، حل میکند.
اکنون به مجموعه حداقلی که از تحقیقات و آزمایشهایم به دست آوردهام، میپردازیم. این فهرست باید با تمامی مرورگرها و دستگاههای محبوب، چه قدیمی و چه جدید، سازگار باشد
### favicon.ico برای مرورگرهای قدیمی
فایلهای ICO میتوانند چندین نسخه از تصویر با اندازههای مختلف را در خود جای دهند. توصیه میکنم از یک تصویر با اندازه ۳۲×۳۲ پیکسل استفاده کنید. نسخه ۱۶×۱۶ را تنها در صورتی ایجاد کنید که لوگو در این اندازه وضوح خود را از دست ندهد یا طراح شما بتواند آن را بهصورت دستی برای این اندازه بازطراحی کند.
بهتر است این فایل را در مسیر دقیق
https://example.com/favicon.ico
نگهداری کنید، بدون استفاده از مسیرهای پیچیده. برخی ابزارها، مانند خوانندگان RSS، مستقیماً /favicon.ico
را از سرور درخواست میکنند و به دنبال آن در مکان دیگری نمیگردند.برای رفع اشکال Chrome که بهجای SVG، فایل ICO را انتخاب میکند، به
sizes="any"
برای تگ <link>
مربوط به فایل .ico
نیاز داریم.### یک آیکون SVG با نسخههای روشن/تاریک برای مرورگرهای مدرن
SVG یک فرمت برداری است که بهجای پیکسلها، منحنیها را توصیف میکند. در اندازههای بزرگ، این روش کارآمدتر از تصاویر شطرنجی است. در زمان نگارش این مقاله، ۷۲٪ از مرورگرها از آیکونهای SVG پشتیبانی میکنند.
صفحه HTML شما باید دارای تگ
<link>
در بخش <head>
با rel="icon"`، `type="image/svg+xml"
و href
باشد که به فایل SVG با این ویژگیها اشاره میکندSVG یک فرمت XML است و میتواند تگ
<style>
برای توصیف CSS داشته باشد. مانند هر CSS دیگری، میتواند شامل مدیا کوئریهایی مانند @media (prefers-color-scheme: dark)
باشد. این امکان را میدهد که همان آیکون بین تمهای روشن و تاریک سیستم تغییر کند.### تصویر PNG با اندازه ۱۸۰×۱۸۰ برای دستگاههای اپل
آیکون Apple touch تصویری برای صفحه اصلی iPhone یا iPad است. در صفحه HTML شما باید تگی با
<link rel="apple-touch-icon" href="apple-touch-icon.png">
در بخش <head>
وجود داشته باشد.از iOS 8 به بعد، برای iPad به تصویری با رزولوشن ۱۸۰×۱۸۰ نیاز است. دستگاههای قدیمیتر آن را بهصورت خودکار مقیاسدهی میکنند.
نکتهای کوچک: آیکون Apple touch بهتر به نظر میرسد اگر حاشیهای به اندازه ۲۰ پیکسل داشته باشد و رنگ پسزمینهای اضافه شود. برای این کار میتوانید از هر ویرایشگر گرافیکی استفاده کنید.
### مانیفست وباپلیکیشن با آیکونهای PNG ۱۹۲×۱۹۲ و ۵۱۲×۵۱۲ برای دستگاههای اندروید
- مانیفست وباپلیکیشن یک فایل JSON است که تمامی جزئیات لازم برای نصب وبسایت شما بهعنوان یک اپلیکیشن سیستمی را فراهم میکند. این فرمت توسط گوگل در چارچوب ابتکار PWA معرفی شده است.
- صفحه HTML شما باید تگی با
<link rel="manifest" href="manifest.webmanifest">
داشته باشد که به فایل مانیفست اشاره میکند.- در مانیفست باید فیلد
icons
وجود داشته باشد که به دو آیکون اشاره میکند: ۱۹۲×۱۹۲ برای نمایش در صفحه اصلی و ۵۱۲×۵۱۲ که بهعنوان صفحه بارگذاری PWA استفاده میشود{
"icons": [
{ "src": "/icon-192.png", "type": "image/png", "sizes": "192x192" },
{ "src": "/icon-512.png", "type": "image/png", "sizes": "512x512" }
]
}
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
«واترمارک» در سال ۲۰۲۵
بسیاری از ما واترمارکها را با چیزی قدیمی و منسوخ مرتبط میکنیم: آنها حواس را پرت میکنند و تجربه بصری محتوا را مختل میسازند. با این حال، گاهی اوقات واترمارک به عنوان یک عنصر ضروری برای پیادهسازی در خواسته مشتری جهت حفاظت از مواد حقوقی او در نظر گرفته میشود.
امروز به شما نشان خواهم داد که چگونه به راحتی و به سرعت میتوان یک واترمارک برای سایت خود با استفاده از SVG و جاوااسکریپت ایجاد کرد.
چگونه این کار میکند؟
من گرافیک SVGای ایجاد میکنم که شامل متنی است با افکت چرخش و شفافیت نیمهشفاف. سپس با استفاده از جاوااسکریپت، این گرافیک SVG را به تصویر تبدیل کرده و آن را به عنوان تصویر پسزمینه برای یک کانتینر خاص در صفحه اعمال میکنم.
اگرچه HTML و CSS استاندارد باقی میمانند، این ویژگی ایجاد واترمارک است که توجه ویژهای را میطلبد.
کد تابع ایجاد واترمارک SVG:
چگونه کد کار میکند؟
ساختار SVG:
داخل رشته SVG یک عنصر SVG ایجاد میشود که متنی را نمایش میدهد، این متن با ویژگیهای HTML از جمله موقعیت، چرخش و شفافیت تنظیم میشود؛
• کدگذاری در Base64:
برای استفاده از این SVG به عنوان پسزمینه، از کدگذاری Base64 استفاده میشود. این امکان را فراهم میکند که تصویر مستقیماً در CSS گنجانده شود، بدون نیاز به بارگذاری فایل جداگانه؛
• روش btoa:
تابع btoa() رشته را به فرمت Base64 تبدیل میکند. با این حال، برای کار درست با نویسههای سیریلیک و دیگر نمادهای غیر-ASCII، باید از روشی با استفاده از TextEncoder بهره گرفت. این روش به جلوگیری از مشکلات کدگذاری کمک خواهد کرد.
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
بسیاری از ما واترمارکها را با چیزی قدیمی و منسوخ مرتبط میکنیم: آنها حواس را پرت میکنند و تجربه بصری محتوا را مختل میسازند. با این حال، گاهی اوقات واترمارک به عنوان یک عنصر ضروری برای پیادهسازی در خواسته مشتری جهت حفاظت از مواد حقوقی او در نظر گرفته میشود.
امروز به شما نشان خواهم داد که چگونه به راحتی و به سرعت میتوان یک واترمارک برای سایت خود با استفاده از SVG و جاوااسکریپت ایجاد کرد.
چگونه این کار میکند؟
من گرافیک SVGای ایجاد میکنم که شامل متنی است با افکت چرخش و شفافیت نیمهشفاف. سپس با استفاده از جاوااسکریپت، این گرافیک SVG را به تصویر تبدیل کرده و آن را به عنوان تصویر پسزمینه برای یک کانتینر خاص در صفحه اعمال میکنم.
اگرچه HTML و CSS استاندارد باقی میمانند، این ویژگی ایجاد واترمارک است که توجه ویژهای را میطلبد.
کد تابع ایجاد واترمارک SVG:
function generateWatermarkSVG(text) {
const svg = `
<svg xmlns="http://www.w3.org/2000/svg" width="220" height="100">
<text x="15" y="70"
transform="rotate(-15, 10, 10)"
fill="rgba(60, 90, 150, 0.16)"
font-size="18"
font-family="sans-serif">
${text}
</text>
</svg>
`.trim();
const encodedSvg = new TextEncoder().encode(svg);
return `data:image/svg+xml;base64,${btoa(String.fromCharCode(...encodedSvg))}`;
}
window.addEventListener("DOMContentLoaded", function() {
const watermarkText = "@IR_javascript";
const container = document.getElementById('watermark-container');
const encodedSvg = generateWatermarkSVG(watermarkText);
container.style.setProperty('background-image', `url(${encodedSvg})`);
});
چگونه کد کار میکند؟
ساختار SVG:
داخل رشته SVG یک عنصر SVG ایجاد میشود که متنی را نمایش میدهد، این متن با ویژگیهای HTML از جمله موقعیت، چرخش و شفافیت تنظیم میشود؛
• کدگذاری در Base64:
برای استفاده از این SVG به عنوان پسزمینه، از کدگذاری Base64 استفاده میشود. این امکان را فراهم میکند که تصویر مستقیماً در CSS گنجانده شود، بدون نیاز به بارگذاری فایل جداگانه؛
• روش btoa:
تابع btoa() رشته را به فرمت Base64 تبدیل میکند. با این حال، برای کار درست با نویسههای سیریلیک و دیگر نمادهای غیر-ASCII، باید از روشی با استفاده از TextEncoder بهره گرفت. این روش به جلوگیری از مشکلات کدگذاری کمک خواهد کرد.
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
رابط برنامهنویسی View Transitions
نوآوری تازهای است که امکان ایجاد انیمیشنهای نرم و طبیعی بین حالتهای مختلف یک صفحه را به سادگی فراهم میکند.
اکنون دیگر نیازی نیست تا انیمیشنهای پیچیده CSS یا JavaScript را بهصورت دستی کدنویسی کنید — مرورگر بهصورت خودکار، گذار روانی بین وضعیت قبلی و وضعیت جدید ایجاد میکند. این کار باعث صرفهجویی در زمان شده و رابطهای کاربری را دلپذیرتر و حرفهایتر جلوه میدهد.
### نمونهای ساده:
در اینجا متد
فراخوانی میشود و یک تابع که شامل تغییرات در DOM است به آن ارسال میگردد. ادامهی فرآیند توسط مرورگر انجام میشود.
### این فرآیند چگونه عمل میکند؟
مرورگر ابتدا وضعیت فعلی صفحه را «ذخیره» میکند، سپس تغییرات را اعمال کرده و وضعیت قبلی و جدید را با یکدیگر مقایسه میکند. در نهایت، خود مرورگر عملیات انیمیشن بین این دو حالت را مدیریت مینماید.
آنچه این ویژگی را بسیار جذابتر میسازد، امکان اتصال مستقیم انیمیشنهای CSS از طریق شبهالمانهایی مانند
است. این قابلیت، انعطافپذیری بیشتری را فراهم میکند: برای نمونه میتوان برای حالت قبلی افکت محو شدن و برای حالت جدید افکت بزرگنمایی در نظر گرفت.
🔗https://codepen.io/katrin_profrontend/pen/OPJqBOx
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
نوآوری تازهای است که امکان ایجاد انیمیشنهای نرم و طبیعی بین حالتهای مختلف یک صفحه را به سادگی فراهم میکند.
اکنون دیگر نیازی نیست تا انیمیشنهای پیچیده CSS یا JavaScript را بهصورت دستی کدنویسی کنید — مرورگر بهصورت خودکار، گذار روانی بین وضعیت قبلی و وضعیت جدید ایجاد میکند. این کار باعث صرفهجویی در زمان شده و رابطهای کاربری را دلپذیرتر و حرفهایتر جلوه میدهد.
### نمونهای ساده:
document.startViewTransition(() =>
updateTheDOMSomehow());
در اینجا متد
document.startViewTransition()
فراخوانی میشود و یک تابع که شامل تغییرات در DOM است به آن ارسال میگردد. ادامهی فرآیند توسط مرورگر انجام میشود.
### این فرآیند چگونه عمل میکند؟
مرورگر ابتدا وضعیت فعلی صفحه را «ذخیره» میکند، سپس تغییرات را اعمال کرده و وضعیت قبلی و جدید را با یکدیگر مقایسه میکند. در نهایت، خود مرورگر عملیات انیمیشن بین این دو حالت را مدیریت مینماید.
آنچه این ویژگی را بسیار جذابتر میسازد، امکان اتصال مستقیم انیمیشنهای CSS از طریق شبهالمانهایی مانند
::view-transition-old
و ::view-transition-new
است. این قابلیت، انعطافپذیری بیشتری را فراهم میکند: برای نمونه میتوان برای حالت قبلی افکت محو شدن و برای حالت جدید افکت بزرگنمایی در نظر گرفت.
🔗https://codepen.io/katrin_profrontend/pen/OPJqBOx
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
codepen.io
View Transitions API
...
کلونکردن عمیق اشیاء واکنشپذیر در Vue 3
Vue 3 از *Proxy* برای واکنشپذیری استفاده میکند، که این مسئله زمانی که بخواهید اشیاء را کلون کنید، مشکلاتی ایجاد میکند. روشهای استاندارد به صورت مورد انتظار عمل نمیکنند:
استفاده از عملگر `...` یا مشابه آن:
اگر شما از عملگر
استفاده از `JSON.stringify` و `JSON.parse`:
وقتی از
### چرا این اتفاق میافتد؟
Vue 3 از *Proxy* برای ایجاد واکنشپذیری استفاده میکند. *Proxy* در واقع یک "نظارتکننده" بر روی اشیاء است که هر تغییر در دادهها را شبیهسازی میکند و به Vue اطلاع میدهد تا رابط کاربری بهروز شود. زمانی که شما از روشهای استاندارد کپی استفاده میکنید، این ویژگیهای *Proxy* نادیده گرفته میشوند و به همین دلیل نمیتوانید از کپیهای انجامشده بهطور کامل استفاده کنید.
سه روش کاربردی برای این کار:
1. ترکیب
2. کپیکردن عمیق دستی
3. استفاده از کتابخانههای موجود
این روشها به شما کمک میکنند تا اشیاء واکنشپذیر را به طور صحیح کلون کنید بدون اینکه ارجاع به *Proxy* حفظ شود یا متدهای آن از بین بروند.
#️⃣#tip #vue
👥@IR_javascript_group
🆔@IR_javascript
Vue 3 از *Proxy* برای واکنشپذیری استفاده میکند، که این مسئله زمانی که بخواهید اشیاء را کلون کنید، مشکلاتی ایجاد میکند. روشهای استاندارد به صورت مورد انتظار عمل نمیکنند:
const state = reactive({ user: { name: "Al" } });
// مشکلات:
const badCopy1 = { ...state }; // حفظ ارجاع به Proxy
const badCopy2 = JSON.parse(JSON.stringify(state)); // از دست دادن متدها و Proxy
استفاده از عملگر `...` یا مشابه آن:
اگر شما از عملگر
...
برای کپی کردن یک شیء واکنشپذیر استفاده کنید، این کپی فقط ارجاع به *Proxy* اصلی را میگیرد، نه خود دادهها. به عبارت دیگر، تغییرات در شیء جدید میتواند بر شیء اصلی تأثیر بگذارد.استفاده از `JSON.stringify` و `JSON.parse`:
وقتی از
JSON.stringify
برای تبدیل شیء به یک رشته و سپس از JSON.parse
برای بازگشایی آن استفاده میکنید، متدهای شیء واکنشپذیر از بین میروند و همچنین ارتباط با *Proxy* قطع میشود. این به این معناست که ویژگیهای واکنشپذیری از دست میروند و این کپی دیگر به صورت واکنشپذیر نخواهد بود.### چرا این اتفاق میافتد؟
Vue 3 از *Proxy* برای ایجاد واکنشپذیری استفاده میکند. *Proxy* در واقع یک "نظارتکننده" بر روی اشیاء است که هر تغییر در دادهها را شبیهسازی میکند و به Vue اطلاع میدهد تا رابط کاربری بهروز شود. زمانی که شما از روشهای استاندارد کپی استفاده میکنید، این ویژگیهای *Proxy* نادیده گرفته میشوند و به همین دلیل نمیتوانید از کپیهای انجامشده بهطور کامل استفاده کنید.
سه روش کاربردی برای این کار:
1. ترکیب
toRaw
و structuredClone
import { toRaw } from 'vue';
const original = reactive({ data: 123 });
const copy = structuredClone(toRaw(original));
2. کپیکردن عمیق دستی
function deepClone(obj) {
if (obj === null || typeof obj !== 'object') return obj;
const clone = Array.isArray(obj) ? [] : {};
for (const key in obj) {
clone[key] = deepClone(obj[key]);
}
return clone;
}
const copy = reactive(deepClone(toRaw(original)));
3. استفاده از کتابخانههای موجود
import { cloneDeep } from 'lodash-es';
const copy = reactive(cloneDeep(toRaw(obj)));
این روشها به شما کمک میکنند تا اشیاء واکنشپذیر را به طور صحیح کلون کنید بدون اینکه ارجاع به *Proxy* حفظ شود یا متدهای آن از بین بروند.
#️⃣#tip #vue
👥@IR_javascript_group
🆔@IR_javascript
👍2
در این پست، 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