React وVue كلاهما أداة JavaScript لبناء واجهات المستخدم من مكوّنات (يسمي React نفسه مكتبة، ويسمي Vue نفسه إطار عمل تدريجيًا)، ويتشاركان معظم الأفكار: props إلى الأسفل، والأحداث إلى الأعلى، والحالة التفاعلية، وDOM افتراضي. والفروق العملية أن React يكتب الترميز بـ JSX ويتوقع أن تُستبدل الحالة بدالة ضبط، بينما يكتب Vue الترميز في قوالب HTML داخل مكوّنات الملف الواحد ويتيح لك تغيير القيم التفاعلية مباشرة. إليك عدّادًا في React:
والعدّاد نفسه كمكوّن ملف واحد في Vue (Counter.vue):
<script setup>
import { ref } from 'vue';
const count = ref(0);
</script>
<template>
<button @click="count++">Clicked {{ count }} times</button>
</template>
يصبح useState(0) هو ref(0)، ويصبح onClick هو @click، ويصبح {count} هو {{ count }}. والفرق الظاهر هو count++: يتيح لك Vue تغيير القيمة في مكانها، ويلاحظ نظام التفاعلية فيه ذلك. أما React فيحتاج إلى setCount لأنه لا يعيد العرض إلا عندما تسلّمه قيمة جديدة.
JSX مقابل مكوّنات الملف الواحد
مكوّن React دالة JavaScript تُرجع JSX. الشروط هي && أو معامل ثلاثي، والقوائم هي .map()، وتأتي الأنماط مما تختاره (ملفات CSS، أو CSS Modules، أو إطار أصناف خدمية).
أما مكوّن Vue فعادة ملف .vue فيه ثلاث كتل: <script setup> للمنطق، و<template> للترميز، و<style scoped> اختيارية لا تنطبق CSS الخاصة بها إلا على ذلك المكوّن. وتستخدم القوالب التوجيهات (directives): v-if وv-for وv-model للربط الثنائي للحقول و:prop لربط قيمة و@event للاستماع. تُبقي القوالب الترميز مقروءًا لكل من يعرف HTML؛ وتعطيك JSX لغة JavaScript كاملة في الترميز. يستطيع Vue استخدام JSX أيضًا ولا يستطيع React استخدام القوالب، لكن معظم الكود في كل منهما يتبع الافتراضي.
إليك قائمة مرشحة، الميزة الثانية للمقارنة.
جرّب كتابة xyz لترى رسالة الفراغ، ثم احذفها. ونسخة Vue:
<script setup>
import { ref, computed } from 'vue';
const fruits = ['Apple', 'Banana', 'Cherry', 'Grape', 'Mango', 'Peach'];
const query = ref('');
const visible = computed(() =>
fruits.filter((f) => f.toLowerCase().includes(query.value.toLowerCase()))
);
</script>
<template>
<input v-model="query" placeholder="Filter fruit" />
<ul>
<li v-for="fruit in visible" :key="fruit">{{ fruit }}</li>
<li v-if="visible.length === 0">No match</li>
</ul>
</template>
يحل v-model محل الزوج value وonChange، ويحل computed محل المتغير العادي. في React تُعاد حساب visible في كل عرض لأن دالة المكوّن تعمل من جديد؛ وفي Vue يخزّنها computed ولا يعيد حسابها إلا عندما تتغير query. ويستخدم كلاهما key للتمييز بين عناصر القائمة.
نموذج التفاعلية
هذا هو أعمق فرق بين الاثنين.
React: حالة غير قابلة للتعديل وإعادة عرض. الحالة لقطة. تستدعي دالة ضبط بقيمة جديدة، فيشغّل React دالة المكوّن من جديد، ويقارن JSX الجديدة بالقديمة، ويحدّث DOM. يقارن React القيم بـ Object.is، فتغيير كائن أو مصفوفة في مكانهما ثم تمرير الشيء نفسه من جديد يبدو كأنه لا تغيير على الإطلاق.
انقر "push() in place" فلا يتغير شيء على الشاشة، لأن المصفوفة هي الكائن نفسه. ثم انقر "New array": يُظهر العرض pushed أيضًا، لأن التعديل السابق حدث فعلًا، لكن React لم يكن لديه سبب للنظر. تتناول صفحة useState هذا النمط بتعمق.
Vue: قيم تفاعلية قابلة للتعديل. يسجّل ref أو كائن reactive من يقرؤه (ref عبر دالة القراءة .value، وكائن reactive عبر وكيل proxy). وعندما تكتب فيه، يعرف Vue بالضبط أي القيم المحسوبة والمراقبين وأجزاء القالب تعتمد عليه ولا يحدّث إلا إياها. في Vue يحدّث items.value.push('pushed') الشاشة. تكتب مراسم أقل، وتتخلى عن ضمان أن القيمة لا تتغير من تحتك أبدًا.
لا أحد النموذجين أسرع بطريقة تهم في التطبيقات المعتادة. قد يشغّل React كودًا أكثر للمكوّنات مع كل تغيير ويعتمد على الحفظ (يدويًا، أو عبر React Compiler) ليتخطى العمل؛ أما Vue فيتتبع الاعتماديات وقت التشغيل فيتخطى ذلك العمل افتراضيًا.
Composition API مقابل الخطافات
يحل Composition API في Vue 3 والخطافات في React المشكلة نفسها: جمع الحالة والمنطق المترابطين معًا وإعادة استخدامهما عبر المكوّنات. يسمي Vue الدوال القابلة لإعادة الاستخدام composables (useMouse())، ويسميها React خطافات مخصصة (useMouse()). وتختلف القواعد بسبب وقت تشغيل الكود.
- متى يعمل. تعمل
setupفي Vue مرة واحدة عند إنشاء المكوّن. أما دالة مكوّن React فتعمل في كل عرض، وتعمل الخطافات بداخلها معها. - قواعد الترتيب. يطابق React الخطافات بترتيب الاستدعاء، فلا يمكنك استدعاؤها داخل شروط أو حلقات. ولا توجد قاعدة كهذه في Vue لـ
refوcomputed، لأن setup تعمل مرة واحدة. - الاعتماديات. تسرد تأثيرات React وقيمها المحفوظة اعتمادياتها في مصفوفة تصونها أنت. أما
watchEffectوcomputedفي Vue فيتتبعان ما يقرآنه تلقائيًا. - القيم القديمة. قد تلتقط دالة استدعاء في React قيمة حالة قديمة من عرض سابق (خطأ
setIntervalالكلاسيكي). أما دالة الاستدعاء في Vue فتقرأcount.valueوقت الاستدعاء وترى دائمًا القيمة الحالية.
يجعل نموذج React كل عرض دالة نقية من props والحالة، وهذا سهل الاختبار والفهم. ويزيل نموذج Vue فئة من الأخطاء حول مصفوفات الاعتماديات. والمطورون الذين يعرفون أحدهما يتعلمون الآخر بسرعة عادة.
المنظومة
| React | Vue | |
|---|---|---|
| الترميز | JSX | قوالب HTML في ملفات .vue (وJSX اختيارية) |
| تحديثات الحالة | استبدل بدالة ضبط، ثم أعد العرض | غيّر قيمة تفاعلية، فتتحدث المعتمدات عليها |
| إعادة استخدام المنطق | الخطافات المخصصة | Composables |
| القيم المشتقة | تُحسب أثناء العرض، وuseMemo | computed (مخزنة) |
| الربط الثنائي للحقول | value مع onChange | v-model |
| CSS محصورة النطاق | غير مدمجة (CSS Modules، أو مكتبات) | <style scoped> مدمجة |
| التوجيه | React Router، وTanStack Router، وأطر العمل | Vue Router (رسمي) |
| الحالة العامة | السياق، وZustand، وRedux Toolkit | Pinia (رسمي) |
| إطار عمل متكامل | Next.js، ووضع إطار العمل في React Router | Nuxt |
| تطبيقات الهاتف | React Native | لا خيار رسمي (Capacitor، وNativeScript-Vue) |
| أداة البناء | Vite أو إطار عمل | Vite |
| تصونه | Meta والمجتمع | فريق أساسي مستقل والمجتمع |
النمط في ذلك الجدول: يصون الفريق الأساسي لـ Vue الموجّه والمخزن وأدوات التطوير معًا، فيكون لمشروع Vue خيار افتراضي واضح لكل منها. ويترك React ذلك للمجتمع، ما يعطيك خيارات أكثر وقرارات أكثر. وVite، أداة البناء المعتادة للمشاريع الجديدة في الاثنين، بدأها مبتكر Vue.
منحنى التعلم
كثيرًا ما يكون Vue البداية الألطف. تُقرأ القوالب مثل HTML التي تعرفها أصلًا، ويزيل v-model الكود المتكرر للحقول المتحكم بها، وتحدّث القيمة التفاعلية الشاشة عندما تغيّرها. أما React فيطلب JSX وعادة التحديث غير المعدِّل منذ البداية، وصفحة JSX هي أول ما يحتاجه معظم الناس.
بعد الأساسيات تضيق الفجوة. يضيف Vue مفاهيمه الخاصة (المراجع مقابل الكائنات التفاعلية، و.value في السكربتات لا في القوالب، والمراقبون)، ويضيف React التأثيرات والحفظ وقواعد الخطافات. وإعلانات الوظائف في منطقتك فاصل أنفع من الصيغة.
متى تختار أيًا منهما
اختر React عندما:
- تريد خيارًا واسعًا من مكتبات المجتمع ومكوّناته، أو تخطط لبناء تطبيقات هاتف أصلية باستخدام React Native.
- تحب إبقاء المنطق والترميز في دالة JavaScript واحدة وتريد إطار عمل مثل Next.js.
- يقدّر فريقك التحديثات الصريحة غير المعدِّلة التي تجعل تتبع كل عرض سهلًا.
اختر Vue عندما:
- تريد أدوات رسمية متوافقة للتوجيه والحالة وقرارات أقل تتخذها.
- يضم فريقك مصممين أو مطوري واجهات خلفية مرتاحين مع قوالب HTML.
- تضيف تفاعلية إلى صفحات قائمة تُعرض على الخادم: يمكن إسقاط Vue في صفحة من وسم script والنمو من هناك.
كلاهما ناضج ومستخدم في الإنتاج لدى شركات من كل الأحجام، والمفاهيم التي تتعلمها في أحدهما (المكوّنات، وprops، والحالة المشتقة، والقوائم ذات المفاتيح) تنتقل مباشرة إلى الآخر.
الأسئلة الشائعة
هل Vue أسهل من React؟
يجد كثير من المبتدئين Vue أسهل في البداية، لأن القوالب تشبه HTML العادية وتغيير قيمة تفاعلية (count.value++) يحدّث الشاشة دون دالة ضبط. أما React فيطلب منك تعلم JSX وقاعدة أن الحالة يجب أن تُستبدل لا أن تُعدَّل. وبعد الأسابيع الأولى تتقارب الصعوبة.
أيهما أفضل، React أم Vue؟
لا أحدهما يفوز عمومًا. يترك React التوجيه والحالة لمكتبات المجتمع ولديه React Native للهاتف. ولدى Vue موجّه ومخزن وأدوات تطوير رسمية تُصان معًا، وقوالب يجدها كثيرون أسهل قراءة. اختر ما يستخدمه فريقك أو سوق العمل لديك.
ما الفرق بين Composition API في Vue والخطافات في React؟
كلاهما يجمع المنطق ذا الحالة في دوال قابلة لإعادة الاستخدام. تعمل setup في Vue مرة واحدة لكل مكوّن وتتتبع الاعتماديات تلقائيًا، فلا توجد مصفوفات اعتماديات ولا إغلاقات قديمة. أما دالة مكوّن React فتعمل في كل عرض، فيجب استدعاء الخطافات بالترتيب نفسه في كل مرة وتسرد التأثيرات اعتمادياتها.
هل يستخدم Vue لغة JSX؟
يدعم Vue لغة JSX عبر إضافة، لكن معظم كود Vue يستخدم قوالب HTML في مكوّنات الملف الواحد (ملفات .vue). أما React فيستخدم JSX في كل مكان تقريبًا.
ما مقابل Next.js في Vue؟
Nuxt. وكما يفعل Next.js مع React، يضيف التوجيه المبني على الملفات والعرض على الخادم والتوليد الثابت ومسارات الخادم فوق Vue.