Vue.js: أساسيات المكونات

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

مكونات Vue هي مثيلات Vue قابلة لإعادة الاستخدام — حيث يحتوي كل مكون على نموذجه الخاص ومنطقه وأنماطه. وتتمثل البنية الأساسية لـ Vue 3 في «شجرة المكونات»: المكون الجذري (App.vue) → مكونات الصفحات → مكونات الأعمال → المكونات الأساسية (Button/Input).

يُعد إتقان أساسيات المكونات خطوة حاسمة في بناء تطبيقات Vue واسعة النطاق. سيساعدك هذا الدرس على فهم طبيعة المكونات، وكيفية تسجيلها، وقواعد تسميتها، ولماذا تُعد مكونات الملف الواحد (SFCs) هي النهج الموصى به في Vue.

1. ما ستتعلمه


2. نظام خلفي للتجارة الإلكترونية من 30 صفحة يعاني من تكرار الأكواد

(1) المشكلة: 30 بطاقة منتج، و30 عملية نسخ ولصق

كانت مسؤولة التجارة الإلكترونية لدى أليس بحاجة إلى عرض 30 بطاقة منتج على عدة صفحات. وكانت طريقتها الأولية هي:

HTML
<!-- ❌ The "Broken" Version: Copy Product Card 30 times -->
<!-- In HomeView.vue -->
<div class="product-card">
  <img src="iphone.jpg">
  <h3>iPhone 15 Pro</h3>
  <p>$999</p>
  <button>Add to Cart</button>
</div>
<div class="product-card">
  <img src="macbook.jpg">
  <h3>MacBook Pro</h3>
  <p>$2499</p>
  <button>Add to Cart</button>
</div>
<!-- ... And also 28 more ... -->

<!-- The same code appears again in ProductList.vue, SearchResults.vue, Cart.vue -->

يضيف مدير المنتج تشارلي 5 متطلبات جديدة:

"أليس، أريد تغيير نص الزر من 'إضافة إلى سلة التسوق' إلى 'إضافة إلى الحقيبة'. كما يجب أن تعرض البطاقة status التوفر. ويجب أن يتكيف التصميم مع أجهزة الجوال."

يتعين على أليس تعديل أكثر من 30 ملف HTML ثلاث مرات = 90 تعديلاً. ومن المستحيل الحفاظ على هذا الوضع.

(2) حل مكونات Vue: ملف ProductCard.vue واحد، أعيد استخدامه 30 مرة

1 ProductCard.vue → أُعيد استخدامه 30 مرة. لتغيير نص الزر، ما عليك سوى إجراء التغيير في مكان واحد فقط.

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

بعد تقسيم النظام إلى مكونات:


3. ما المقصود بالمكون؟

(1) التعريف

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

100%
graph TB
    A[App.vue<br/>Root Component] --> B[HomeView.vue<br/>Home]
    A --> C[AboutView.vue<br/>About]
    A --> D[DashboardView.vue<br/>Dashboard]
    
    B --> E[ProductCard.vue<br/>Product Card]
    B --> F[ProductList.vue<br/>Product List]
    B --> G[FilterBar.vue<br/>Filter Bar]
    
    E --> H[Button.vue<br/>Button]
    E --> I[Badge.vue<br/>Badge]
    
    F --> E
    G --> J[Select.vue<br/>Scroll down]
    G --> K[Input.vue<br/>Input]
    
    style A fill:#42b883,color:#fff
    style E fill:#42b883,color:#fff
    style H fill:#42b883,color:#fff

(2) 5 ميزات رئيسية

الميزة الوصف
قابل لإعادة الاستخدام يمكن استخدام مكون واحد في N أماكن
التغليف فصل البيانات والأساليب والأسلوب بحيث لا تتداخل فيما بينها
نظام المكونات مكونات أصغر تُجمع معًا لتشكيل مكونات أكبر
قابل للاختبار اختبار الوحدة لمكون واحد
قابلية الصيانة تغيير مكان واحد = تغيير N أماكن

(3) المكونات مقابل الوظائف

البعد الوظيفة المكون
المكونات القابلة لإعادة الاستخدام منطق البرمجة واجهة المستخدم + المنطق
المدخلات الحجج (args) الخصائص (props)
الإخراج الإرجاع الإرسال
الstatus المتغيرات المحلية البيانات / المراجع
الآثار الجانبية لا شيء ربطات دورة الحياة

4. مكون ملف واحد (SFC)

(1) ما هو SFC؟

SFC (مكون ملف واحد) = ملف .vue واحد = مكون واحد. إن دمج الأقسام template وscript وstyle في ملف واحد يسهل عملية إدارتها.

(2) شرح مفصل للجزء الثالث من قانون الأوراق المالية والبورصات (SFC)

القسم الوظيفة هل هي مطلوبة؟ اللغة
<template> قالب HTML ✅ أمر HTML + Vue
<script setup> JS Logic ✅ JavaScript / TypeScript
<style scoped> أنماط CSS ❌ CSS / SCSS / Less

(3) سلسلة SFC مقابل سلسلة HTML

JS
// ❌ No need SFC(String Templates,Vue 2 Style)
Vue.component('my-component', {
  template: '<div>{{ msg }}</div>',
  data() { return { msg: 'Hello' } }
})

// ✅ Use SFC (Recommended)
// MyComponent.vue
<template>
  <div>{{ msg }}</div>
</template>
<script setup>
const msg = 'Hello'
</script>

مزايا SFC:

▶ مثال: مكون ProductCard.vue المكون من ملف واحد

▶ جرّب الكود

الإخراج:

TEXT
بطاقة تعرض صورة المنتج واسمه وسعره
stock = 5 → Only 5 left والزر مفعّل
stock = 0 → Out of Stock والزر معطّل
بعد النقر: emit add-to-cart بمعرّف المنتج

5. تسجيل المكونات

(1) التسجيل الشامل (لا يُنصح به للمشاريع الكبيرة)

JS
// main.js
import { createApp } from 'vue'
import App from './App.vue'
import ProductCard from './components/ProductCard.vue'

const app = createApp(App)

// Global Registration:All components are available <ProductCard />
app.component('ProductCard', ProductCard)

app.mount('#app')

(2) التسجيل المحلي (موصى به)

VUE
<!-- HomeView.vue -->
<script setup>
// 1. Import
import ProductCard from '@/components/ProductCard.vue'

// 2. Use in a template(No registration required,Automatically Available)
</script>

<template>
  <ProductCard :product="product" />
</template>

(3) مقارنة بين طريقتي التسجيل

البعد التسجيل العالمي التسجيل المحلي
النطاق التطبيق بأكمله المكون الحالي
موقع الرمز main.js داخل المكون <script setup>
تغيير هيكل الشجرة ❌ غير مدعوم ✅ مدعوم
تلميحات الأنواع ضعيفة قوية (الإكمال التلقائي في IDE)
التوصية ⭐⭐ للمكونات الإضافية ⭐⭐⭐⭐⭐ للاستخدام التجاري

▶ مثال: مقارنة بين التسجيل العالمي والتسجيل المحلي

JS
// ❌ main.js Global Registration(Not recommended)
import ProductCard from './components/ProductCard.vue'
app.component('ProductCard', ProductCard)  // The entire app is available

// ✅ HomeView.vue Local Registration(Recommendations)
<script setup>
import ProductCard from '@/components/ProductCard.vue'
// Only at HomeView.vue Available in China
</script>
▶ جرّب الكود

الإخراج:

TEXT
التسجيل العالمي: ProductCard متاح في كل القوالب
التسجيل المحلي: متاح داخل HomeView فقط
حجم الحزمة أصغر مع التسجيل المحلي

6. قواعد تسمية المكونات

(1) 3 قواعد تسمية

النمط المثال الاستخدام التوصية
PascalCase ProductCard.vue استيراد JS / في القوالب ⭐⭐⭐⭐⭐
kebab-case product-card.vue أسماء الملفات / قوالب kebab-case ⭐⭐⭐
camelCase productCard.vue غير موصى به ⭐

(2) الاستخدام في القوالب

(3) هيكل المجلدات

TEXT
src/
├-- components/          # Public Components(For use across pages)
│   ├-- ProductCard.vue
│   ├-- Button.vue
│   └-- Header.vue
├-- views/               # Page Components(For routing)
│   ├-- HomeView.vue
│   ├-- ProductListView.vue
│   └-- DashboardView.vue
├-- composables/         # Composite Functions
│   ├-- useAuth.ts
│   └-- useFetch.ts
├-- router/              # Router Configuration
└-- App.vue              # Root Component

7. أساسيات props و emit

(1) العناصر المساعدة: تنتقل من العنصر الأصلي إلى العنصر التابع

(2) الإرسال: من العنصر الفرعي إلى العنصر الأصلي

(3) دليل مرجعي سريع: props مقابل emit

الفئة واجهة برمجة التطبيقات (API) الغرض
الأصل → الفرع defineProps() نقل البيانات
الطفل → الوالد defineEmits() إخطار بالحدث

▶ مثال: الأنواع الخمسة الرئيسية للأدوات المسرحية

VUE
<script setup>
defineProps({
  // Basic Types
  name: String,
  age: Number,
  active: Boolean,
  
  // Complex Types
  user: Object,
  items: Array,
  
  // Required + Default value
  title: { type: String, required: true },
  pageSize: { type: Number, default: 20 },
  
  // Validator
  email: { 
    type: String, 
    validator: (val) => val.includes('@') 
  },
  
  // Custom Types
  status: { 
    type: String, 
    validator: (val) => ['active', 'inactive'].includes(val) 
  }
})
</script>
▶ جرّب الكود

الإخراج:

TEXT
props تُعرّف بـ String و Number و Boolean و Object و Array
title مطلوب و pageSize افتراضي 20
validator يرفض بريدًا بلا @
status يقبل active أو inactive فقط

(1) 📊 5. 5 مبادئ تصميم المكونات

المبدأ الوصف
المسؤولية الواحدة كل مكون يقوم بمهمة واحدة
قابل لإعادة الاستخدام واجهة مستخدم مجردة وعامة (أزرار/حقول إدخال/نوافذ منبثقة)
قابل للتكوين تتحكم الخصائص (props) في السلوك، بينما تتحكم الفتحات (slots) في المحتوى
نظام المكونات مكونات أصغر تُجمع معًا لتشكيل مكونات أكبر
سهولة الاختبار المكونات المستقلة تجعل اختبار الوحدات أمرًا سهلاً

(2) 📊 6. 5 أخطاء شائعة

الخطأ الأعراض الحل
ملف قائمة المكونات خطأ في بيئة التطوير المتكاملة استخدم أسلوب PascalCase: ProductCard.vue
عدد كبير جدًا من التسجيلات العالمية حجم حزمة أكبر التسجيلات المحلية تدعم ميزة «tree-shaking»
المكون كبير جدًّا يصعب صيانته قسّمه إلى مكونات أصغر
تعديل الخصائص مباشرةً تحذير من Vue الخصائص مخصصة للقراءة فقط؛ استخدم emit بدلاً من ذلك
نسيت استيراد مكون القالب يعرض عبارة "مكون غير معروف" تحقق من عملية الاستيراد في <script setup>


8. تمرين شامل: إعادة استخدام ProductCard في ثلاث صفحات

▶ مثال: إعادة استخدام «ProductCard» في 3 صفحات

VUE
<!-- src/views/HomeView.vue -->
<template>
  <h1>Featured Products</h1>
  <div class="grid">
    <ProductCard 
      v-for="product in featured" 
      :key="product.id" 
      :product="product"
      @add-to-cart="handleAdd"
    />
  </div>
</template>

<script setup>
import { ref } from 'vue'
import ProductCard from '@/components/ProductCard.vue'
import { useCart } from '@/composables/useCart'

const featured = ref([
  { id: 1, name: 'iPhone 15 Pro', price: 999, stock: 50, image: 'iphone.jpg' },
  { id: 2, name: 'MacBook Pro', price: 2499, stock: 20, image: 'macbook.jpg' }
])

const { addToCart } = useCart()
function handleAdd(productId) {
  addToCart(productId)
}
</script>
▶ جرّب الكود
VUE
<!-- src/views/ProductListView.vue -->
<template>
  <ProductCard 
    v-for="product in products" 
    :key="product.id" 
    :product="product"
    @add-to-cart="handleAdd"
  />
</template>

<script setup>
import ProductCard from '@/components/ProductCard.vue'
// ... Exactly the same citation,Reusable Components
</script>

الإخراج:

TEXT
HomeView يعرض بطاقتين من featured
ProductListView يعرض البطاقة نفسها بلا تكرار كود
النقر يمرّر add-to-cart إلى handleAdd


❓ أسئلة شائعة

س متى ينبغي استخدام التسجيل العام؟
ج في حالتين فقط: (1) مكونات المكونات الإضافية (مثل <el-button> من Element Plus)؛ (2) المكونات الأساسية المستخدمة في جميع أنحاء التطبيق (الأزرار/الأيقونات). أما المكونات التجارية فيجب تسجيلها محليًّا دائمًا حتى تصبح عملية «تصفية الشجرة» سارية المفعول.
س هل يجب أن يتضمن SFC الأجزاء الثلاثة جميعها؟
ج <template> و<script> مطلوبان؛ أما <style> فهو اختياري. إذا كان المكون يتألف من لغة JavaScript فقط (على سبيل المثال، إذا كان مخصصًا لتغليف البيانات فقط)، فيمكن حذف القالب (باستخدام الدالة render) بدلاً من ذلك.
س ما هو الحجم المناسب لملف المكون؟
ج نوصي بأن لا يتجاوز عدد الأسطر فيه 200 سطر. إذا تجاوز عدد الأسطر 300 سطر، ففكر في تقسيمه. فكلما كان المكون أبسط، زادت سهولة صيانته.
س يستخدم SFC الامتداد .vue. كيف تتعرف عليه الأدوات الأخرى؟
ج تتعرف كل من Vite وWebpack وVue CLI على الامتداد .vue بشكل افتراضي. أما بالنسبة لـ VS Code، فقم بتثبيت ملحق "Vue - Official".
س كيف يمكنني اختبار مكون واحد؟
ج استخدم Vitest + Vue Test Utils (@vue/test-utils): mount(ProductCard, { props: { product: mockProduct } }). تتناول المرحلة 4.6 من هذا الدليل هذا الموضوع بالتفصيل.
س كيف يمكنني استخدام مكتبة المكونات (Element Plus)؟
ج قم بالتثبيت عبر npm → قم بالتسجيل عالميًا في ملف main.js → استخدم <el-button> مباشرةً في قوالبك. لمزيد من التفاصيل، راجع الفصل 4.7 من Phase.
س ما الفرق بين SFC و React JSX؟
ج تستخدم SFC قوالب شبيهة بـ HTML (قريبة من معايير الويب)، بينما تستخدم React JSX (كتابة HTML باستخدام JavaScript). تتميز SFC بسهولة التعلم، في حين أن JSX تتميز بالمرونة ولكنها تتطلب خطوة بناء. يدعم Vue 3 أيضًا JSX (@vitejs/plugin-vue-jsx)، لكن SFC هو الخيار الموصى به افتراضيًا.

📖 ملخص


📝 تمارين

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

    كتابة مكون زر src/components/BaseButton.vue:

    • المعلمات: text (سلسلة)، variant (سلسلة، 'primary'/'success'/'danger')
    • هناك 3 أنواع تتوافق مع 3 فئات
    • إصدار حدث click
    • استخدم 3 أشكال مختلفة في ملف HomeView.vue
  2. مسائل متقدمة (مستوى الصعوبة: ⭐⭐)

    إنشاء قائمة منتجات + نظام البطاقات:

    • ProductCard.vue: بطاقة منتج واحد (الخصائص: product، الإشارة: add-to-cart)
    • ProductList.vue: حاوية قائمة المنتجات (v-for + التصفية)
    • App.vue: المكون الجذري؛ يقوم بتمرير البيانات والتعامل مع حدث "الإضافة إلى سلة التسوق"
    • 3 ملفات و3 مكونات مستخدمة في بنية متداخلة
  3. مسألة التحدي (مستوى الصعوبة: ⭐⭐⭐)

    تنفيذ نظام مكونات «بطاقة المستخدم» متكامل:

    1. Avatar.vue: مكون الصورة الرمزية (يدعم كل من وضع عنوان URL ووضع الأحرف الأولى)
    2. UserCard.vue: بطاقة المستخدم (مع الصورة الرمزية)
    3. UserList.vue: قائمة المستخدمين (باستخدام UserCard)
    4. App.vue: المكون الجذري (البيانات + التفاعل)
    5. 5 خصائص (الصورة الرمزية/الاسم/البريد الإلكتروني/الدور/status النشاط)
    6. 3 أحداث (تحرير/حذف/تحديد)
    7. عزل الأنماط المحددة النطاق
Web-Tutorial.com

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

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

100%