Vue.js: دورة حياة المكون

آخر تحديث: 2026-08-26

دورة حياة المكون هي العملية الكاملة التي يمر بها مكون Vue من الإنشاء إلى الإزالة: إنشاء مثيل → التثبيت في DOM → تحديثات البيانات → إلغاء التثبيت. توفر Vue ثمانية ربطات لدورة الحياة تتيح لك تنفيذ التعليمات البرمجية في أوقات محددة.

يُعد فهم دورة الحياة أمرًا أساسيًّا لكتابة مكونات «حية» — حيث يمكنك تحميل البيانات عند التثبيت، وتنفيذ الآثار الجانبية عند التحديث، وتنظيف الموارد عند إلغاء التثبيت.

1. ما ستتعلمه



2. مشكلة «الوميض» في أحد مكونات تحميل البيانات

(1) المشكلة: تم عرض المكون، لكن البيانات لم تُحمَّل بعد

قامت أليس بإنشاء مكون لملف تعريف المستخدم:

VUE
<!-- ❌ The "Broken" Version:Rendering Before Data Arrives -->
<template>
  <div>
    <h1>{{ user.name }}</h1>
    <p>{{ user.email }}</p>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const user = ref({})  // Empty object,Display during rendering "undefined"
fetch('/api/user')
  .then(res => res.json())
  .then(data => user.value = data)
</script>

تجربة المستخدم:

مدير المنتج تشارلي:

"أليس، يظهر للمستخدمين عبارة 'غير محدد' لمدة نصف ثانية. نحن بحاجة إلى status تحميل. اعرضي عبارة 'جاري التحميل...' حتى تصل البيانات."

(2) دورة حياة Vue + حل لstatus "التحميل"

VUE
<template>
  <div>
    <p v-if="loading">Loading...</p>
    <div v-else>
      <h1>{{ user.name }}</h1>
      <p>{{ user.email }}</p>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted } from 'vue'

const user = ref(nulo)
const loading = ref(true)

// ✅ Load data in onMounted... (DOM Ready, loading status will be displayed first)
onMounted(async () => {
  const res = await fetch('/api/user')
  user.value = await res.json()
  loading.value = false
})
</script>

تجربة المستخدم:

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

بعد إضافة «دورة الحياة»:



3. مخطط تدفق دورة الحياة الكاملة

100%
graph TB
    A[Create a component instance] --> B[onBeforeCreate]
    B --> C[setup Responsive]
    C --> D[onCreated]
    D --> E[Template Compilation]
    E --> F[onBeforeMount]
    F --> G[Mount to DOM]
    G --> H[onMounted]
    H --> I{Data Update?}
    I -->|Yes| J[onBeforeUpdate]
    J --> K[Render Again]
    K --> L[onUpdated]
    L --> I
    I -->|No| M{Component Uninstall?}
    M -->|Yes| N[onBeforeUnmount]
    N --> O[Unmount]
    O --> P[onUnmounted]
    
    style H fill:#42b883,color:#fff
    style L fill:#42b883,color:#fff
    style P fill:#42b883,color:#fff


4. شرح مفصل لـ 8 نقاط ربط في دورة الحياة

(1) دليل مرجعي سريع للخطافات الثمانية الرئيسية

العنصر شروط التشغيل السيناريوهات الشائعة التكرار
onBeforeMount قبل تركيب المكونات إعداد البيانات
onMounted بعد تحميل المكون تحميل البيانات، عمليات DOM ⭐⭐⭐⭐⭐
onBeforeUpdate قبل تحديث البيانات تحسين الأداء ⭐⭐
onUpdated بعد تحديث البيانات العمليات التي تلي إعادة عرض DOM ⭐⭐⭐
onBeforeUnmount قبل تفريغ أحد المكونات مسح المؤقتات ⭐⭐⭐
onUnmounted بعد إلغاء تثبيت المكون التنظيف النهائي ⭐⭐
onErrorCaptured تم رصد خطأ في المكون الفرعي حدود الخطأ ⭐⭐⭐
onActivated تم تمكين ميزة Keep-Alive تمت استعادة مكون ذاكرة التخزين المؤقت ⭐⭐
onDeactivated ميزة «keep-alive» معطلة مكون التخزين المؤقت معطل ⭐⭐

(2) onMounted: الأكثر استخدامًا

VUE
<script setup>
import { ref, onMounted } from 'vue'

const user = ref(null)

onMounted(async () => {
  // 1. Loading initial data
  const res = await fetch('/api/user')
  user.value = await res.json()
  
  // 2. DOM Operations(Realistic operation DOM)
  document.title = `${user.value.name} - Dashboard`
  
  // 3. Register a global event listener
  window.addEventListener('resize', handleResize)
  
  // 4. Set a Timer
  const timer = setInterval(() => {
    console.log('Tick')
  }, 1000)
  
  // ❌ Note: onUnmounted must clean up timer and listener
})
</script>

(3) onUnmounted: تنظيف الموارد

VUE
<script setup>
import { onMounted, onUnmounted } from 'vue'

let timer = nulo

onMounted(() => {
  timer = setInterval(() => console.log('Tick'), 1000)
  window.addEventListener('resize', handleResize)
})

// ✅ Cleanup:Avoiding Memory Leaks
onUnmounted(() => {
  clearInterval(timer)
  window.removeEventListener('resize', handleResize)
})
</script>

(4) onErrorCaptured: حدود الخطأ

VUE
<!-- ErrorBoundary.vue Parent Component -->
<script setup>
import { onErrorCaptured, ref } from 'vue'

const error = ref(null)

onErrorCaptured((err, instance, info) => {
  console.error('Caught error:', err)
  console.log('Component:', instance)
  console.log('Info:', info)
  
  error.value = err.message
  return false  // Prevent errors from propagating upward
})
</script>

<template>
  <div>
    <p v-if="error" class="error">Error: {{ error }}</p>
    <slot v-else />
  </div>
</template>
VUE
<!-- App.vue Usage -->
<ErrorBoundary>
  <UserProfile :user-id="123" />  <!-- If an error occurs, will be caught by ErrorBoundary -->
</ErrorBoundary>

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

السيناريو العنصر الجاذب الكود
تحميل البيانات الأولية onMounted await fetch(...)
ضبط المؤقت onMounted + onUnmounted setInterval + clearInterval
تابع آخر الأحداث العالمية
معالجة DOM onMounted document.querySelector(...)
دمج المكتبات الخارجية onMounted + onUnmounted new Chart(...) + chart.destroy()


5. ترتيب تنفيذ دورات حياة المكونات الأم والمكونات التابعة

(1) ترتيب التثبيت

100%
sequenceDiagram
    participant P as Parent
    participant C as Child
    
    P->>P: 1. Parent onBeforeMount
    P->>P: 2. Parent onMounted
    C->>C: 3. Child onBeforeMount
    C->>C: 4. Child onMounted
    
    Note over P,C: ❌ That's wrong: Parent mounted should come after Child

الترتيب الصحيح:

100%
sequenceDiagram
    participant P as Parent
    participant C as Child
    
    P->>P: 1. Parent onBeforeMount
    C->>C: 2. Child onBeforeMount
    C->>C: 3. Child onMounted
    P->>P: 4. Parent onMounted
    
    Note over P,C: ✅ Mount only after all child components, including the parent component, have finished mounting

(2) أمر التنفيذ الكامل (المكونات المتداخلة)

TEXT 📖 للعرض فقط
1. Parent onBeforeCreate
2. Parent setup
3. Parent onCreated
4. Parent onBeforeMount
5. Child onBeforeCreate
6. Child setup
7. Child onCreated
8. Child onBeforeMount
9. Child onMounted
10. Parent onMounted

(3) ترتيب إلغاء التثبيت (بالترتيب العكسي)

TEXT 📖 للعرض فقط
1. Parent onBeforeUnmount
2. Child onBeforeUnmount
3. Child onUnmounted
4. Parent onUnmounted


6. مكون التخزين المؤقت «Keep-Alive»

(1) ما المقصود بـ «keep-alive»؟

<keep-alive> يقوم بتخزين مثيلات المكونات مؤقتًا لتجنب تكرار إنشائها وإزالتها. ويُستخدم عادةً في الحالات التي تنطوي على التبديل بين علامات التبويب والتبديل بين المسارات.

VUE
<!-- Parent Component -->
<template>
  <button v-for="tab in tabs" :key="tab" @click="currentTab = tab">
    {{ tab }}
  </button>
  
  <!-- keep-alive Package:Switch Tab Do not destroy the component -->
  <keep-alive>
    <component :is="currentTabComponent" />
  </keep-alive>
</template>

(2) خطافان جديدان

VUE
<!-- Child component: Cached by keep-alive -->
<script setup>
import { onActivated, onDeactivated } from 'vue'

// When the component is activated(Restore from Cache)
onActivated(() => {
  console.log('Component activated')
  // Reload Data,Restore scroll position, etc.
})

// When a component is disabled(Cut but keep in cache)
onDeactivated(() => {
  console.log('Component deactivated')
  // Save Status,Pause the timer, etc.
})
</script>

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

السيناريو الطريقة
التبديل بين علامات التبويب <keep-alive> لف محتوى tag التبويب
تبديل المسار حزمة <keep-alive> <router-view>
ذاكرة التخزين المؤقتة للنوافذ المنبثقة <keep-alive> نافذة منبثقة للحزمة
صفحة القوائم القوائم المخزنة مؤقتًا التي تم تحميلها
صفحة النموذج تخزين النماذج التي لم يتم إرسالها مؤقتًا


7. مثال كامل: مكون ملف تعريف المستخدم

▶ مثال: 1. onMounted + onUnmounted (تحميل البيانات + التنظيف)

VUE
<template>
  <div>
    <p v-if="loading">Loading...</p>
    <div v-else-if="user">
      <h1>{{ user.name }}</h1>
      <p>{{ user.email }}</p>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue'

const props = defineProps({ userId: { type: Number, required: true } })
const user = ref(null)
const loading = ref(true)

let timer = null

onMounted(async () => {
  // 1. Loading data
  const res = await fetch(`/api/users/${props.userId}`)
  user.value = await res.json()
  loading.value = false
  
  // 2. Set a Timer (Every 30s Refresh)
  timer = setInterval(async () => {
    const res = await fetch(`/api/users/${props.userId}`)
    user.value = await res.json()
  }, 30000)
  
  // 3. Monitoring Window Size Changes
  window.addEventListener('resize', () => {
    console.log('Window resized')
  })
})

onUnmounted(() => {
  // ✅ Cleanup:Avoiding Memory Leaks
  clearInterval(timer)
  window.removeEventListener('resize', () => {})
})
</script>
▶ جرّب الكود

▶ مثال: 2. مرجع سريع لـ 8 خطافات

VUE
<script setup>
import { 
  onBeforeMount, onMounted, 
  onBeforeUpdate, onUpdated,
  onBeforeUnmount, onUnmounted,
  onErrorCaptured, onActivated, onDeactivated 
} from 'vue'

// 1. Before Mounting
onBeforeMount(() => {
  console.log('1. Preparing to mount')
})

// 2. After mounting(Most Commonly Used)
onMounted(() => {
  console.log('2. Mounted,Loading data')
})

// 3. Before the update
onBeforeUpdate(() => {
  console.log('3. Coming Soon')
})

// 4. After the update
onUpdated(() => {
  console.log('4. Updated')
})

// 5. Before Uninstalling
onBeforeUnmount(() => {
  console.log('5. Preparing to uninstall,Free Up Resources')
})

// 6. After uninstallation
onUnmounted(() => {
  console.log('6. Uninstalled')
})

// 7. Error Handling
onErrorCaptured((err) => {
  console.erro('7. Child Component Error:', err)
  return false
})

// 8. keep-alive Activate
onActivated(() => {
  console.log('8. keep-alive Activate')
})

// 9. keep-alive Disable
onDeactivated(() => {
  console.log('9. keep-alive Disable')
})
</script>
▶ جرّب الكود

▶ مثال: 3. ترتيب دورة حياة المكونات الأم والمكونات التابعة

VUE
<!-- Parent.vue -->
<template>
  <Child :data="parentData" />
</template>

<script setup>
import { onMounted } from 'vue'
onMounted(() => console.log('4. Parent mounted'))
</script>

<!-- Child.vue -->
<template>
  <p>{{ data }}</p>
</template>

<script setup>
import { onMounted } from 'vue'
onMounted(() => console.log('3. Child mounted'))
</script>

<!-- Order of Console Output:
1. Child created
2. Child mounted
3. Parent mounted
(Because the parent component must wait until the child component has finished mounting before it can mount itself) -->
▶ جرّب الكود

▶ مثال: 4. حدود الخطأ onErrorCaptured

VUE
<!-- ErrorBoundary.vue -->
<script setup>
import { onErrorCaptured, ref } from 'vue'

const error = ref(null)

onErrorCaptured((err, instance, info) => {
  console.error('Caught error:', err)
  console.log('Component:', instance?.$options.name)
  console.log('Info:', info)  // 'render' / 'watch' / 'lifecycle hook'
  
  error.value = err.message
  return false  // Prevent upward transmission
})
</script>

<template>
  <div v-if="error" class="error-banner">
    ⚠️ Error: {{ error }}
  </div>
  <slot v-else />
</template>
▶ جرّب الكود

▶ مثال: 5. مكون التخزين المؤقت لـ keep-alive

VUE
<!-- TabContainer.vue -->
<template>
  <div classe="tabs">
    <button 
      v-for="tab in tabs" 
      :key="tab"
      :classe="{ active: currentTab === tab }"
      @click="currentTab = tab"
    >
      {{ tab }}
    </button>
    
    <!-- keep-alive Cache: Preserve component state when switching away -->
    <keep-alive>
      <component :is="currentTabComponent" />
    </keep-alive>
  </div>
</template>

<script setup>
import { ref, computed } from 'vue'
import Home from './tabs/Home.vue'
import Profile from './tabs/Profile.vue'
import Settings from './tabs/Settings.vue'

const tabs = ['Home', 'Profile', 'Settings']
const currentTab = ref('Home')

const currentTabComponent = computed(() => {
  return { Home, Profile, Settings }[currentTab.value]
})
</script>
▶ جرّب الكود

▶ مثال: 6. مرجع سريع لـ 5 أخطاء شائعة

الخطأ الأعراض الحل
استخدم document في المستوى الأعلى من setup خطأ في الخادم استخدم onMounted
لم يتم مسح المؤقت تسرب في الذاكرة مسح في onUnmounted
تعديل المتغيرات في onMounted تحذير Vue استخدم emit بدلاً من ذلك
المكونات غير المتزامنة لا تتعامل مع الأخطاء الفشل الصامت onErrorCaptured
الترتيب الخاطئ لتركيب العناصر الأصلية والتابعة توضيح الالتباس في تصحيح الأخطاء فهم مبدأ «العنصر الأصلي يساوي العنصر التابع»


❓ أسئلة شائعة

س ما الفرق بين onMounted وonCreated؟
ج عند استدعاء onCreated، يكون المكون قد تم إنشاؤه ولكن لم يتم عرض DOM بعد (لذلك لا يمكنك التعامل مع DOM). وعند استدعاء onMounted، يكون DOM قد تم تثبيته (لذلك يمكنك التعامل مع DOM). يتم التعامل مع تحميل البيانات عمومًا في onMounted (لتجنب مشكلات SSR).
س هل يمكن أن تكون خطافات دورة الحياة غير متزامنة؟
ج نعم. onMounted(async () => { await fetch(...) }) هي صيغة صحيحة. لا تنتظر Vue اكتمال العملية غير المتزامنة قبل المتابعة.
س ما الفرق بين onActivated وonMounted في keep-alive؟
ج يتم تشغيل onMounted مرة واحدة فقط (عند التثبيت الأولي). أما onActivated فيتم تشغيله في كل مرة يتم فيها استعادة العرض من ذاكرة التخزين المؤقت. ويؤدي التبديل بين علامات التبويب إلى تشغيل onActivated وonDeactivated (وليس onMounted وonUnmounted).
س ما أنواع الأخطاء التي يمكن لـ onErrorCaptured رصدها؟
ج يمكنه رصد ثلاثة أنواع: (1) أخطاء عرض المكونات الفرعية؛ (2) أخطاء خطافات دورة حياة المكونات الفرعية؛ (3) أخطاء استدعاءات رد الفعل الخاصة بمراقبة المكونات الفرعية. ومع ذلك، لا يمكنه رصد أخطائه الخاصة أو الأخطاء غير المتزامنة.
س هل يمكن للمكون الأصلي الاستماع إلى أحداث دورة حياة المكون التابع؟
ج نعم. يمكنك استخدام @hook للاستماع: @hook:mounted="handleChildMounted". ومع ذلك، يُنصح باستخدام props/emit للتواصل بدلاً من الاستماع مباشرةً إلى أحداث دورة الحياة.
س ما هي الاختلافات بين خطافات دورة الحياة في Vue 2 و Vue 3؟
ج أعادت Vue 3 تسمية الخطاف إلى onMounted (كان mounted في Vue 2) وأضافت onErrorCaptured و onActivated/onDeactivated. جميع خطافات Vue 2 متوفرة في Vue 3 (تم الحفاظ على التوافق مع الإصدارات السابقة).
س ماذا يحدث لدورة الحياة أثناء عملية العرض من جانب الخادم (SSR)؟
ج لا يتم تشغيل أحداث onBeforeMount وonMounted وonBeforeUpdate وonUpdated على الخادم (نظرًا لعدم وجود DOM). ولا يتم تشغيل سوى أحداث onBeforeCreate وonCreated وonBeforeUnmount وonUnmounted وonErrorCaptured.

📖 ملخص


📝 تمارين

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

    تنفيذ مكون UserCard بسيط:

    • onMounted: تحميل بيانات المستخدم (محاكاة تأخير مدته ثانية واحدة)
    • إظهار «جاري التحميل» → إظهار معلومات المستخدم
    • سجلات onUnmounted: "تم إتلاف المكون"
  2. مسائل متقدمة (مستوى الصعوبة: ⭐⭐)

    تنفيذ مكون «المؤقت»:

    • onMounted: بدء تشغيل مؤقت (+1 في الثانية)
    • عرض الثانية الحالية
    • onUnmounted: مسح المؤقت
    • إضافة زر للإيقاف المؤقت/الاستئناف (استخدم ref لتخزين الstatus)
  3. مسألة التحدي (مستوى الصعوبة: ⭐⭐⭐)

    تنفيذ نظام علامات تبويب كامل:

    1. TabContainer.vue: 3 علامات تبويب (الصفحة الرئيسية/الملف الشخصي/الإعدادات)
    2. 3 مكونات لمحتوى علامات التبويب
    3. استخدم مكون التخزين المؤقت <keep-alive>
    4. تبديل tag التبويب «X نشط، Y غير نشط»
    5. قم بتحميل البيانات في إحدى علامات التبويب باستخدام onMounted
    6. لا يتم إغلاق الاتصال عند الانتقال إلى تطبيق آخر (بسبب ميزة «keep-alive»)، لذا تظل البيانات موجودة عند العودة إلى التطبيق الأصلي
    7. استخدم onErrorCaptured لتحديد الأخطاء في المكونات الفرعية
Web-Tutorial.com

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

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

100%