provide() وinject() لحقن الاعتماديات
وفّر القيم في مكوّن سلف واحنقها بعمق داخل الشجرة، متجنبًا تمرير props عبر مستويات متعددة دون الحاجة إلى مكتبة كاملة لإدارة الحالة
provide() وinject() لحقن الاعتماديات درس مجاني في Frontend Academy على CoddyKit. هذا هو الدرس 1 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Frontend Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Frontend Academy 4 دروس في المجموع.
مشكلة تمرير الخصائص
توجد البيانات أحيانًا في مكوّن علوي، وتحتاج إلى الوصول إلى عنصر منحدر عميق. تمريرها عبر كل مكوّن وسيط (prop drilling) أمر مرهق وعرضة للأخطاء.
provide() — الإعلان عن قيمة
يستدعي أحد الأسلاف provide(key, value) في setup(). وتصبح القيمة متاحة لجميع العناصر المنحدرة منه.
<!-- ParentComponent.vue -->
<script setup>
import { provide, ref } from 'vue';
const theme = ref('dark');
provide('theme', theme);
</script>inject() — استهلاك قيمة
يستدعي أي عنصر منحدر inject(key) لقراءة القيمة.
<!-- DeepChild.vue -->
<script setup>
import { inject } from 'vue';
const theme = inject('theme');
</script>
<template>
<div :class="theme">Theme is: {{ theme }}</div>
</template>التفاعلية مع ref/reactive
إذا وفّرت كائن ref أو reactive، تحصل العناصر المنحدرة على قيمة تفاعلية، وتنتقل التحديثات تلقائيًا.
// Parent
const user = reactive({ name: 'Alice', role: 'admin' });
provide('user', user);
// Anywhere descendant
const user = inject('user');
user.role; // 'admin' — reactiveمفاتيح Symbol لتجنب التعارضات
تعرّض المفاتيح النصية لخطر التعارض في التطبيقات الكبيرة. تضمن رموز Symbol التفرد، لذا عرّفها في ملف مشترك.
// keys.ts
export const ThemeKey = Symbol('theme');
export const UserKey = Symbol('user');
// Parent
provide(ThemeKey, ref('dark'));
// Child
const theme = inject(ThemeKey);دعم TypeScript
استخدم InjectionKey<T> لضمان أمان الأنواع في الطرفين.
import type { InjectionKey, Ref } from 'vue';
export const ThemeKey: InjectionKey<Ref<string>> = Symbol('theme');
// Provider:
provide(ThemeKey, ref('dark'));
// Consumer (type-checked):
const theme = inject(ThemeKey); // Ref<string> | undefinedالقيم الافتراضية
إذا لم يوفّر أي سلف المفتاح، يعيد inject القيمة undefined، ما لم تمرّر قيمة افتراضية.
const theme = inject('theme', 'light'); // default if missing
const lazy = inject('user', () => createDefaultUser(), true); // factoryالقيم الموفَّرة للقراءة فقط
لمنع العناصر المنحدرة من تعديل الحالة المشتركة، أحطها بـ readonly().
import { readonly } from 'vue';
const user = reactive({ name: 'Alice' });
provide('user', readonly(user));
// Children can read but cannot mutateالتوفير على مستوى التطبيق
وفّر القيم على مستوى التطبيق لتصبح متاحة في كل مكان، وهذا مفيد للمكوّنات الإضافية.
// main.ts
import { createApp } from 'vue';
import App from './App.vue';
const app = createApp(App);
app.provide('apiClient', new ApiClient());
app.mount('#app');غلاف Composable
أحط provide/inject داخل Composable للحصول على واجهة برمجية أنظف للمستهلك.
// useTheme.ts
import { inject, type InjectionKey, type Ref } from 'vue';
export const ThemeKey: InjectionKey<Ref<string>> = Symbol('theme');
export function useTheme() {
const theme = inject(ThemeKey);
if (!theme) throw new Error('useTheme: no provider in tree');
return theme;
}provide/inject مقابل Pinia
provide/inject: خفيف، ولا يحتاج إلى مكتبة، ومثالي للقيم ذات نمط المكوّنات الإضافية مثل السمة واللغة والمستخدم الحالي. Pinia: إدارة كاملة للحالة مع DevTools، ومثالية للحالة التفاعلية على مستوى التطبيق عندما تكون التحديثات معقدة.
تحقق سريع
ما الطريقة الموصى بها لتجنب تعارض المفاتيح عند استخدام provide/inject في تطبيق Vue كبير؟
مراجعة: provide/inject
يوفّر السلف القيمة ويحقنها العنصر المنحدر، من دون تمرير الخصائص. تنتقل القيم التفاعلية (ref/reactive) تفاعليًا. توفر مفاتيح Symbol مع InjectionKey حقنًا آمنًا من ناحية الأنواع وخاليًا من التعارضات. تكون القيمة الافتراضية الوسيط الثاني لـ inject. استخدم readonly() لمنع التعديل. يتيح التوفير على مستوى التطبيق استخدام المكوّنات الإضافية عبر التطبيق. وهو بديل خفيف لـ Pinia للقيم ذات نمط المكوّنات الإضافية.
الأسئلة الشائعة
هل درس «provide() وinject() لحقن الاعتماديات» مجاني؟
نعم — نص درس «provide() وinject() لحقن الاعتماديات» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Frontend Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Frontend Academy 4 دروس في المجموع.
ماذا ستتعلم في «provide() وinject() لحقن الاعتماديات»؟
وفّر القيم في مكوّن سلف واحنقها بعمق داخل الشجرة، متجنبًا تمرير props عبر مستويات متعددة دون الحاجة إلى مكتبة كاملة لإدارة الحالة تتمرن على Frontend Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Frontend Academy؟
لا تُشترط خبرة سابقة. Frontend Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 1 من أصل 4.
كم من الوقت يستغرق درس «provide() وinject() لحقن الاعتماديات»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Frontend Academy هذا؟
نعم. كل درس في Frontend Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- provide() وinject() لحقن الاعتماديات
- المكوّنات غير المتزامنة وSuspense
- التوجيهات المخصّصة
- نظام الإضافات: app.use()