Vue / المتوسط: حالة الميزة وملكية الأثر / الدرس 7
دورة الحياة والوصول إلى DOM وتنظيف الأثر
طابق عمل المتصفح مع عمر المكوّن وميّز تغير الحالة من اكتمال العرض.
في هذه الصفحة
أهداف الدرس
- سجل خطافات الدورة في سياق setup الصحيح.
- اقرن المستمع والمؤقت بتنظيف صريح.
امنح العمل الخارجي مالكاً
قد يمتلك المكوّن اشتراكات ومؤقتات ومراقبين وتنسيق طلبات مع الحالة. تتوقف الآثار عند انتهاء الحاجة. تربط الخطافات العمل بالربط والتحديث والإزالة، ويكون التسجيل متزامناً في setup النشط. لا يمنح تسجيل مؤخر عشوائي الملكية نفسها. اجمع الغرض والتنظيف بوضوح، ولا يعني إخفاء v-show الإزالة؛ الرؤية والعمر قراران مختلفان.
أخر وصول المتصفح لمرحلته المناسبة
يبدأ المثال بعرض محايد ويقرأ window بعد الربط، فيبعد العام المتصفحي عن setup الذي قد يعمل بالخادم. يستخدم المعالج نفسه للتسجيل والإزالة ولا يعيده بكل تحديث. هو أثر عرض صغير لا توصية لبناء التجاوب كله بـ JavaScript؛ فضل CSS حيث يكفي. وثق واجهة إيقاف المراقب أو المكتبة واستدعها لدى المالك المناسب.
<script setup>
import { ref, onMounted, onUnmounted } from "vue"
const width = ref(null)
function updateWidth() { width.value = window.innerWidth }
onMounted(() => {
updateWidth()
window.addEventListener("resize", updateWidth)
})
onUnmounted(() => window.removeEventListener("resize", updateWidth))
</script>
<template>
<p>{{ width === null ? "Measuring window" : `Width: ${width}` }}</p>
</template>
يتطلب مكوّناً مربوطاً بالمتصفح. يسبق المخرج المحايد قراءة العرض وتزيل الإزالة المعالج. لم ينفذ السلوك والعرض والتنظيف في متصفح لهذا الجزء.
اقرأ DOM بعد التحديث المطلوب
يسبق تغيير المرجع إفراغ عمل DOM أحياناً. استخدم nextTick لحاجة المعالج للنتيجة أو مراقبة post لانتقال محدد، لا نوماً ينجح على آلة واحدة. قد يكون template ref فارغاً قبل الربط أو بعد الشرط فافحص العمر. لا تنافس Vue بكتابة الخاصية نفسها مباشرة. ادمج المكتبة بحد معزول بقواعد تحديث وتنظيف.
اختبر عقد التنظيف دون متصفح فعلي
يمكن فحص مساعد إيقاف بهدف وهمي. يسجل المثال الكامل المعالجات في Set ويفحص إزالة المعالج نفسه. لا يثبت استدعاء Vue للخطاف لكنه يثبت عقد المساعد. افصل الطبقتين واختبر التكامل بربط المالك وإزالته. تختلف المؤقتات والمراقب والاشتراك فاستخدم إلغاء كل واجهة لا تفترض أنها جميعاً مستمع.
function subscribe(target, handler) {
target.addEventListener("change", handler)
return () => target.removeEventListener("change", handler)
}
const active = new Set()
const target = {
addEventListener: (_name, handler) => active.add(handler),
removeEventListener: (_name, handler) => active.delete(handler)
}
const dispose = subscribe(target, () => {})
if (active.size !== 1) throw new Error("SUBSCRIPTION_MISSING")
dispose()
if (active.size !== 0) throw new Error("SUBSCRIPTION_LEAK")
يعمل بـ Node وبيانات الذاكرة فقط وينتقل العدد من واحد لصفر. لا يصل إلى DOM أو مستمع أو مؤقت أو خدمة ولا يدعي تغطية دورة الإطار.
راجع العمر المخزن والخادمي منفصلين
قد يعطل KeepAlive المكوّن دون تدميره فتحتاج آثار التوقف خطافات النشاط. تختلف دورة SSR ولا تعمل خطافات المتصفح؛ لا تنشئ مؤقتاً طويل العمر في setup الخادم وتتوقع تنظيف الإزالة. قد يكمل غير المتزامن بعد تغير المالك فيحتاج إبطالاً. راجع التكرار والشرط وإعادة المسار والتخزين، ليملك كل أثر حداً مبرراً مختبراً.
الأخطاء الشائعة وإصلاحها
يتراكم المستمع بعد الزيارات
- لماذا يحدث؟
- يغيب تنظيف مطابق للتسجيل.
- كيف تصلحه؟
- أزل المعالج نفسه أو أوقف المورد بدورته.
- كيف تتجنب تكراره؟
- اختبر الربط والإزالة المتكررين.
يغيب window أثناء العرض الخادمي
- لماذا يحدث؟
- يعمل المتصفحي في setup المشترك.
- كيف تصلحه؟
- انقل الأثر لحد دورة العميل.
- كيف تتجنب تكراره؟
- راجع تنفيذ الخادم والعميل منفصلين.
يستخدم مرجع قالب بعد غياب عقدته
- لماذا يحدث؟
- غير الشرط عمر DOM.
- كيف تصلحه؟
- احمِ المرجع وطابق الأثر بالحضور.
- كيف تتجنب تكراره؟
- ضمّن الإزالة الشرطية بالتحقق.
اختبر فهمك
1. تخفى لوحة بـ v-show. هل تعمل onUnmounted حينها؟
اعرض الحل المشروح
لا؛ يبقى الفرع ولا تزيله إخفاء display. إذا لزم توقف العمل فمثل الرؤية صراحة ولا تعتمد خطاف إزالة لن يعمل.
2. ينجح اختبار الإيقاف للمساعد. ماذا يتحقق اختبار المكوّن؟
اعرض الحل المشروح
يتحقق من زمن التسجيل واستدعاء الإيقاف عند نهاية المالك أو تعطيله وعدم التكرار. لا تثبت الدالة الخالصة تفاعلات الإطار.
أهم ما تعلمته
- للآثار الخارجية ملكية وتنظيف صريحان.
- يختلف توقيت الحالة وDOM.
- تنشئ الرؤية والتخزين والخادم أعماراً مختلفة.