Vue.js: ميزات Vue 3.4 الجديدة

آخر تحديث: 2026-10-20

يقدم إصدار Vue 3.4+ (الذي صدر في ديسمبر 2023) عدة تحسينات ثورية: defineModel تبسيط الماكرو v-model، وتفكيك الخصائص التفاعلية useTemplateRef، وواجهة برمجة التطبيقات (API) للتركيب useId، وإنشاء معرّفات فريدة. تعمل هذه الميزات على تبسيط كود template بشكل كبير وتحسين تجربة التطوير.

سيساعدك هذا الدرس على إتقان خمس ميزات جديدة أساسية ستجعل كود Vue 3 الخاص بك أكثر إيجازًا وحداثة.

التوجيهات ذات صلة:v-model

1. ما ستتعلمه


2. تحدي «التزامن بين العنصر الأصلي والعنصر التابع» في أحد مكونات نموذج v

(1) المشكلة: 5 أسطر من «props» + 5 أسطر من «emit» = 10 أسطر من النص النمطي

قامت أليس بإنشاء مكون إدخال مخصص باستخدام v-model:

JS
// ❌ The "Broken" Version:v-model Required 10 Sample Code
const props = defineProps({ modelValue: String })
const emit = defineEmits(['update:modelValue'])

const internalValue = ref(props.modelValue)
watch(() => props.modelValue, (val) => {
  internalValue.value = val
})
watch(internalValue, (val) => {
  emit('update:modelValue', val)
})

10 أسطر من الكود النمطي — يجب عليك كتابة هذا لكل مكون من مكونات نموذج V.

المطور الرئيسي:

"أليس، هذا النص مطول جدًّا. يتوفر في Vue 3.4 defineModel الذي يقوم بذلك في سطر واحد."

(2) الشكل 3.4: الحل العام لماكرو defineModel

JS
// ✅ Correct Version:1 All set v-model
const modelValue = defineModel('modelValue')

// It's possible now:
// - Read: modelValue.value
// - Write: modelValue.value = 'new value' (Automatic emit)
// - watch:watch(modelValue, ...)
// - Parent Component v-model Two-way binding works as usual

10 أسطر → سطر واحد. توفر المكونات الخمسة لنموذج V 50 سطراً من التعليمات البرمجية.

(3) الإيرادات

بعد الترقية إلى defineModel:


3. شرح مفصل لماكرو defineModel

(1) الاستخدام الأساسي

(2) 5 استخدامات متقدمة

JS
// 1. Default value
const modelValue = defineModel('modelValue', { default: '' })

// 2. Type Constraints(TypeScript)
const count = defineModel<number>('count', { default: 0 })

// 3. transform Convert(Conversion at the Time of Writing)
const trimmed = defineModel('text', {
  set(value) {
    return value.trim()  // Automatic trim
  }
})

// 4. getter(Conversion During Reading)
const upper = defineModel('text', {
  get(value) {
    return value.toUpperCase()  // Always uppercase
  }
})

// 5. Several v-model
const name = defineModel('name')
const email = defineModel('email')
const phone = defineModel('phone')

(3) مثال كامل

▶ جرّب الكود
VUE
<!-- Parent Component -->
<CustomInput v-model="name" />
<!-- User Input "alice" → trim Unchanged → uppercase → "ALICE" -->

▶ مثال: 5 طرق لاستخدام defineModel

VUE
<!-- 1. Basics -->
<script setup>
const modelValue = defineModel('modelValue')
</script>

<!-- 2. Default value -->
<script setup>
const count = defineModel('count', { default: 0 })
</script>

<!-- 3. TypeScript Type -->
<script setup lang="ts">
const user = defineModel<User>('user', { default: () => ({}) })
</script>

<!-- 4. transform Convert -->
<script setup>
const trimmed = defineModel('text', {
  set(val) { return val?.trim() || '' }
})
</script>

<!-- 5. Several v-model -->
<script setup>
const username = defineModel('username')
const password = defineModel('password')
</script>
▶ جرّب الكود

الإخراج:

TEXT
تعديل الحقل في المكوّن التابع ينعكس على المكوّن الأصلي فورًا بلا emits يدوي
مع default: يبدأ count من 0 إذا لم يمرر الأب قيمة
مع set: تُخزَّن النصوص مقصوصة من المسافات الطرفية
username وpassword يعملان كـ v-model مستقلين في المكوّن نفسه

4. تفكيك الخصائص التفاعلية

(1) المشكلات التي كانت موجودة قبل إصدار Vue 3.4

JS
// ❌ Vue 3.3 and before that
const props = defineProps({ count: Number, name: String })

// Use directly in the template props.count
// JS Key Points props.count
// Deconstruction may result in a loss of response
const { count, name } = props  // count/name Convert to a regular value

(2) Vue 3.4: تفكيك المتغيرات مع الحفاظ على سرعة الاستجابة

تظل العناصر المساعدة المُفككة تفاعلية! وهذا أحد أكبر التحسينات في Vue 3.4.

(3) 5 سيناريوهات رئيسية للتطبيق

JS
// 1. Simplify props Usage
const { count, name } = defineProps<{ count: numbervalue; name: string }>()

// 2. Deconstruction + Rename
const { count: total, name: userName } = defineProps<{ count: numbervalue; name: string }>()

// 3. Deconstruction + Default value
const { count = 0, name = 'Guest' } = defineProps<{ count?: numbervalue; name?: string }>()

// 4. In conjunction with watch(After deconstruction watch Still working)
const { count } = defineProps<{ count: numbervalue }>()
watch(count, (newVal) => console.log('count changed:', newVal))

// 5. In conjunction with computed(Stay responsive as well)
const { count } = defineProps<{ count: numbervalue }>()
const double = computed(() => count * 2)

(4) ملاحظات مهمة

JS
// ⚠️ Deconstructed props Cannot be reassigned
const { count } = defineProps<{ count: number }>()
count = 10  // ❌ Error:Assignment to constant variable

// ✅ Correct:Via emit Have the parent component modify
const emit = defineEmits(['update:count'])
const handleClick = () => emit('update:count', count + 1)

▶ مثال: تفكيك الخصائص التفاعلية

▶ جرّب الكود

الإخراج:

TEXT
العرض الأول: 0 - Alice
بعد النقر على +1 → يُرسل update:count بالقيمة 1 ويصبح العرض: 1 - Alice

5. useId: المعرّف الفريد

(1) لماذا نحتاج إلى useId؟

أثناء عملية العرض من جانب الخادم (SSR)، قد تتسبب المعرّفات المكتوبة يدويًّا في حدوث تعارضات (استخدام عدة مثيلات للمكون نفسه باستخدام المعرّف نفسه). يقوم useId بإنشاء معرّفات فريدة عالميًّا وآمنة للاستخدام مع SSR.

JS
// ❌ Old notation:Handwritten ID,SSR There will be a conflict
const id = `input-${Math.random()}`

// ✅ Vue 3.4+:useId
import { useId } from 'vue'
const id = useId()  // 'v-0', 'v-1', ...

(2) 5 حالات استخدام رئيسية

(3) 5 مزايا رئيسية

الميزة الوصف
أمان SSR مطابقة معرّف الخادم/العميل
فريد لا يحدث تعارض بين المثيلات المتعددة في نفس الصفحة
مستقر لا يزال إعادة عرض المكونات دون تغيير
قابل للقراءة تتضمن المعرّفات البادئة v- لتسهيل التعرف عليها
خفيف الوزن 0 تبعيات (مُدمجة في Vue)

6. useTemplateRef (شرح مفصل لـ Vue 3.5+)

(1) الميزات الكاملة

VUE
<template>
  <input ref="usernameInput">
  <MyChart ref="chartComponent" :data="chartData" />
</template>

<script setup lang="ts">
import { useTemplateRef, onMounted } from 'vue'
import MyChart from './MyChart.vue'

// ✅ Vue 3.5+:One Name Does It All
const inputRef = useTemplateRef<HTMLInputElement>('usernameInput')
const chartRef = useTemplateRef<InstanceType<typeof MyChart>>('chartComponent')

// ✅ TypeScript Perfect Inference
onMounted(() => {
  inputRef.value?.focus()  // HTMLInputElement Type
  chartRef.value?.refresh()  // Component Instance Methods
})
</script>

(2) مقارنة بين Vue 3.5 و Vue 3.4

البعد متغير ref في Vue 3.4 useTemplateRef في Vue 3.5
مرجع القالب <input ref="inputRef"> <input ref="usernameInput">
مرجع JS const inputRef = ref(null) const inputRef = useTemplateRef('usernameInput')
استدلال الأنواع يدوي ref<HTMLInputElement | null> الاستدلال التلقائي
اتساق الأسماء لا يتم الإبلاغ عن الأخطاء الإملائية المحتملة يتم الإبلاغ عن حالات عدم الاتساق
الإيجاز سطران سطر واحد

▶ مثال: استكمال الطلب باستخدام useTemplateRef

VUE
<template>
  <input ref="usernameInput" v-model="username">
  <MyChart ref="chartComponent" :data="chartData" />
</template>

<script setup lang="ts">
import { ref, useTemplateRef, onMounted } from 'vue'
import MyChart from './MyChart.vue'

const username = ref('')
const chartData = ref([1, 2, 3])

// ✅ Vue 3.5+:TypeScript Perfect Inference
const inputRef = useTemplateRef<HTMLInputElement>('usernameInput')
const chartRef = useTemplateRef<InstanceType<typeof MyChart>>('chartComponent')

onMounted(() => {
  inputRef.value?.focus()
  chartRef.value?.refresh()
})
</script>
▶ جرّب الكود

الإخراج:

TEXT
بعد mount يحصل حقل usernameInput على التركيز ويُستدعى refresh() على المخطط
السلوك مطابق للنسخة العادية، لكن الأنواع تُستنتج تلقائيًا دون تحويل يدوي

7. 5 مسارات الترقية الموصى بها

(1) وقت الترقية

إصدار Vue تاريخ الإصدار الstatus
Vue 3.0 سبتمبر 2020 إصدار قديم (يُنصح بالترقية)
Vue 3.2 أغسطس 2021 إصدار مستقر
Vue 3.3 مايو 2023 إصدار مستقر
Vue 3.4 ديسمبر 2023 موصى به حاليًا
Vue 3.5 سبتمبر 2024 أحدث إصدار مستقر

(2) قائمة الترقيات

TEXT
✅ Vue 3.4:
  - defineModel Macro Replacement v-model Complex Notation
  - Responsive props Deconstruction
  - Abbreviations with the Same Name(<input :value> Replace :value="value")
  - Improvements to Error Handling
  - Template Parser Override(2x Performance)

✅ Vue 3.5:
  - useTemplateRef(Recommendations)
  - Responsive props Deconstruction and Improvement
  - useId Stable
 - Deferred teleport
  - Improved Suspense

(3) توصيات الترقية

السيناريو التوصية
مشروع جديد استخدام Vue 3.5+ مباشرةً
مشروع قديم (Vue 3.3–) الترقية إلى الإصدار 3.5، الترحيل حسب الميزة
مشروع قديم (Vue 3.0–3.2) الترقية إلى الإصدار 3.3، ثم إلى الإصدار 3.5
المشاريع الضخمة التحديثات التدريجية (تحديث Vue أولاً، ثم ترحيل v-model، وما إلى ذلك)

8. تمرين شامل: useId ومعرّفات ARIA

▶ مثال: حالات الاستخدام الرئيسية لـ useId 5

▶ جرّب الكود

الإخراج:

TEXT
يُولَّد معرّف مثل v-0 ويُربط به label وحقل الإدخال
عند ظهور خطأ يُنشأ عنصر بالمعرّف v-0-error مرتبط بالحقل عبر aria-errormessage

(1) 📊 5. مرجع سريع لـ 5 أخطاء شائعة

الخطأ الأعراض الحل
تفكيك defineModel لا توجد استجابة استخدم const modelValue = defineModel() مباشرةً
التعيين بعد تفكيك خصائص props خطأ استخدم emit للسماح للعنصر الأصلي بالتحديث
useId مع سلسلة نصية مبرمجة ثابتًا تعارض في SSR التبديل إلى useId()
اسم useTemplateRef غير صحيح ref.value قيمة فارغة يجب أن يتطابق الاسم
يتطلب الترقية إلى Vue 3.4+ تغييرات كثيرة جدًّا مشكلات التوافق الترحيل التدريجي

(2) 📊 6. 5 مزايا رئيسية للترقية إلى Vue 3.4 أو أحدث

الإيرادات البيانات
تقليل حجم الكود 30–50% (تبسيط defineModel)
تحسينات في الأداء تحليل القوالب أسرع بمقدار الضعف
استدلال الأنواع دقة 100% (TypeScript)
متوافق مع SSR استخدام useId لحل تعارضات المعرّفات
تجربة المطور تحسينات كبيرة في تجربة المطور

التوجيهات ذات صلة:v-model

❓ أسئلة شائعة

س هل يحل defineModel محل الصيغة الكاملة لـ v-model؟
ج نعم. defineModel('modelValue') is equivalent to the 10 lines of code in props.modelValue + emit('update:modelValue'). وهو متوافق تمامًا مع الإصدارات السابقة.
س متى سيتم دعم تفكيك الخصائص التفاعلية؟
ج في الإصدار Vue 3.4 وما بعده (ديسمبر 2023). غير مدعوم في الإصدار Vue 3.3 والإصدارات الأقدم. تظل الخصائص المفككة تفاعلية (التفاعلية العميقة هي الإعداد الافتراضي).
س هل يتغير useId مع كل عملية عرض؟
ج لا. يظل المعرّف الذي يتم إنشاؤه بواسطة useId ثابتًا طوال دورة حياة المكون (متسقًا بين SSR والعميل).
س ما الفرق بين useTemplateRef ومتغيرات ref؟
ج تم تقديم useTemplateRef في الإصدار Vue 3.5 وما بعده؛ وهو يوفر استدلالًا أقوى لأنواع TypeScript وإعادة تسمية أكثر أمانًا. أما بالنسبة للمشاريع العادية، فتكفي متغيرات ref.
س هل يمكن استخدام عملية تفكيك defineProps مع watch؟
ج نعم. تعمل const { count } = defineProps() + watch(count, ...) بشكل مثالي.
س كيف يمكنني الترقية من Vue 3.3 إلى 3.4+؟
ج npm update vue@latest. على مستوى الكود: استخدم defineModel بدلاً من بناء الجملة المعقد v-model؛ واستخدم تفكيك المتغيرات التفاعلي بدلاً من props.xxx. دون أي أعطال.
س ما هي التحسينات التي أدخلتها Vue 3.5+ على TypeScript؟
ج التفكيك التفاعلي باستخدام defineProps، والاستدلال التام على الأنواع باستخدام useTemplateRef، ودعم أكثر شمولاً لـ TypeScript فيما يتعلق بالماكرو. نوصي باستخدام <script setup lang="ts">.

📖 ملخص


📝 تمارين

  1. أسئلة أساسية (مستوى الصعوبة: ⭐)

    إعادة هيكلة مكون نموذج v باستخدام defineModel:

    • المكون الفرعي CustomInput.vue: سطر واحد من defineModel
    • المكون الأصلي: الربط ثنائي الاتجاه في نموذج v
    • يدعم القيم الافتراضية
  2. مسائل متقدمة (مستوى الصعوبة: ⭐⭐)

    إعادة كتابة المكونات باستخدام التفكيك التفاعلي في Vue 3.4+:

    • تفكيك الخصائص مثل «count» و«name» وغيرها
    • باستخدام الساعة + الحساب
    • اختبار التصميم المتجاوب
  3. مسألة التحدي (مستوى الصعوبة: ⭐⭐⭐)

    مثال على عملية ترقية كاملة إلى Vue 3.4+:

    1. استبدال بناء الجملة المعقد لنموذج V بـ defineModel في 5 مكونات
    2. تفكيك 3 مكونات باستخدام عناصر تفاعلية
    3. 5 مكونات تستخدم useId (لربط label وinput)
    4. 3 مكونات تستخدم useTemplateRef (Vue 3.5+)
    5. 5 مكونات TypeScript ذات الأنواع القوية
    6. اختبار اتساق useId في سيناريو SSR
Web-Tutorial.com

فريق Web-Tutorial التقني

منصة دروس برمجية يديرها عدة مطورين. كل درس يتم كتابته ومراجعته بواسطة مطورين متخصصين في المجال. نعمل على ضمان دقة وموثوقية المحتوى — إذا لاحظت أي مشكلة، فيرجى إخبارنا.

100%