مراجع القالب
بينما يخفي نموذج التصيير التصريحي لـ Vue معظم عمليات DOM المباشرة بالنسبة لك، فقد يكون هناك حالات تحتاج فيها إلى الوصول المباشر إلى عناصر DOM الأساسية. للوصول إلى هذا، يمكننا استخدام السمة الخاصة ref :
template
<input ref="input">ref هو سمة خاصة، مماثلة لسمة key التي تم مناقشتها في محور v-for. يسمح لنا بالحصول على مرجع مباشر لعنصر DOM محدد أو نسخة مكون ابن بعد وصله. قد يكون هذا مفيدًا عندما تريد، على سبيل المثال، التركيز برمجيًا على عنصر إدخال على مكون موصول بالـ DOM أو تهيئة مكتبة طرف ثالث على عنصر معين.
الوصول إلى المراجع
للحصول على المرجع باستخدام الواجهة التركيبية (Composition API)، يمكننا استخدام الدالة المساعدة useTemplateRef() :
vue
<script setup>
import { useTemplateRef, onMounted } from 'vue'
// يجب أن يطابق الوسيط الأول قيمة `ref` في القالب
const input = useTemplateRef('my-input')
onMounted(() => {
input.value.focus()
})
</script>
<template>
<input ref="my-input" />
</template>عند استخدام TypeScript، يستنتج دعم Vue في المحرّر وvue-tsc تلقائيًا نوع input.value حسب العنصر أو المكون الذي تُستخدم عليه سمة ref المطابقة.
الاستخدام قبل الإصدار 3.5
في الإصدارات السابقة لـ 3.5 حيث لم تُعرَف useTemplateRef() بعد، نحتاج إلى التصريح بمرجع (ref) اسمه يطابق قيمة سمة مرجع القالب في القالب:
vue
<script setup>
import { ref, onMounted } from 'vue'
// التصريح بمتغير تفاعلي لحفظ مرجع العنصر
// يجب أن يكون الاسم مطابق لقيمة مرجع القالب
const input = ref(null)
onMounted(() => {
input.value.focus()
})
</script>
<template>
<input ref="input" />
</template>إذا كنت لا تستخدم <script setup>، تأكد من إرجاع المرجع (ref) من ()setup أيضًا :
js
export default {
setup() {
const input = ref(null)
// ...
return {
input
}
}
}لاحظ أنه يمكنك الوصول إلى المرجع فقط بعد وصل المكون (mount). إذا حاولت الوصول إلى input في تعبير القالب، ستكون القيمة null في التصيير الأول. ذلك لأن العنصر لا يوجد حتى بعد التصيير الأول!
إذا كنت تحاول مراقبة تغييرات مرجع القالب، تأكد من إدراج الحالة حيث يكون مرجع القالب ذو قيمة معدومة null :
js
watchEffect(() => {
if (input.value) {
input.value.focus()
} else {
// غير موصول بعد، أو العنصر أزيل (على سبيل المثال ،بواسطة v-if)
}
})اطلع أيضًا على : إضافة الأنواع للمراجع
المراجع داخل حلقات v-for
يتطلب الإصدار 3.5 أو أحدث
لما يُستخدم المرجع ref داخل v-for، يجب أن يحتوي المرجع المقابل على قيمة مصفوفة، والتي ستُملأ بالعناصر بعد وصل المكون :
vue
<script setup>
import { ref, useTemplateRef, onMounted } from 'vue'
const list = ref([
/* ... */
])
const itemRefs = useTemplateRef('items')
onMounted(() => console.log(itemRefs.value))
</script>
<template>
<ul>
<li v-for="item in list" ref="items">
{{ item }}
</li>
</ul>
</template>الاستخدام قبل الإصدار 3.5
في الإصدارات السابقة لـ 3.5 حيث لم تُعرَف useTemplateRef() بعد، نحتاج إلى التصريح بمرجع (ref) اسمه يطابق قيمة سمة مرجع القالب في القالب. يجب أن يحمل المرجع أيضًا قيمة مصفوفة:
vue
<script setup>
import { ref, onMounted } from 'vue'
const list = ref([
/* ... */
])
const itemRefs = ref([])
onMounted(() => console.log(itemRefs.value))
</script>
<template>
<ul>
<li v-for="item in list" ref="itemRefs">
{{ item }}
</li>
</ul>
</template>تجب الإشارة إلى أن مرجع المصفوفة لا يضمن نفس الترتيب الذي تحتوي عليه المصفوفة المصدرية.
المراجع المُنشأة بالدوال
بدلاً من القيمة النصية، يمكن أيضاً ربط السمة ref بدالة، والتي ستُستدعى في كل تحديث للمكون وتُعطيك الحرية الكاملة في مكان تخزين مرجع العنصر. تستقبل الدالة مرجع العنصر كأول وسيط :
template
<input :ref="(el) => { /* انسب el إلى متغير تفاعلي أو خاصية */ }">تجدر الإشارة إلى أننا نستخدم ربط ديناميكي :ref لذا نستطيع تمرير دالة بدلاً من سلسلة نصية تحتوي على اسم المرجع. عند فصل العنصر، سيكون الوسيط null. بالطبع، يمكنك استخدام تابع/دالة بدلاً من دالة سطرية.
مرجع على مكون
هذا القسم يفترض معرفتك بـالمكونات. يمكنك تخطيه والعودة إليه لاحقاً.
ref يمكن أيضاً استخدامه على مكون ابن. في هذه الحالة، سيكون المرجع على نسخة مكون :
vue
<script setup>
import { useTemplateRef, onMounted } from 'vue'
import Child from './Child.vue'
const childRef = useTemplateRef('child')
onMounted(() => {
// childRef.value سيحتوي على نسخة من <Child />
})
</script>
<template>
<Child ref="child" />
</template>الاستخدام قبل الإصدار 3.5
vue
<script setup>
import { ref, onMounted } from 'vue'
import Child from './Child.vue'
const child = ref(null)
onMounted(() => {
// سيحتوي child.value على نسخة من <Child />
})
</script>
<template>
<Child ref="child" />
</template>إذا كان المكون الابن يستخدم واجهة الخيارات أو لا يستخدم <script setup>، سيكون المرجع المستخدم مطابقاً لـ this للمكون الابن، مما يعني أن المكون الأب سيكون لديه الوصول الكامل إلى كل خاصيات ودوال المكون الابن. هذا يجعل من السهل إنشاء ارتباطات قوبة بين المكون الأب والابن، لذا يجب استخدام مراجع المكونات فقط عند الحاجة القصوى - في معظم الحالات، يجب عليك محاولة تنفيذ التفاعلات بين المكون الأب والابن باستخدام واجهة الخاصيات وإرسال الأحداث القياسية أولاً.
الاستثناء هنا هو أن المكونات التي تستخدم <script setup> هي خاصة (private) افتراضياً: لن يتمكن المكون الأب من الوصول إلى أي شيء إلا إذا اختار المكون الابن تعريف واجهة عامة باستخدام التعليمة defineExpose:
vue
<script setup>
import { ref } from 'vue'
const a = 1
const b = ref(2)
//لا تحتاج التعليمات العامة للمصرف مثل defineExpose لأن تكون مستوردة
defineExpose({
a,
b
})
</script>عندما يحصل المكون الأب على نسخة من هذا المكون عبر مراجع القالب، سيكون المكون المسترجع على الشكل { a: number, b: number } (المراجع تُفك تلقائياً مثل المكونات العادية).
تنبّه إلى أنه يجب استدعاء defineExpose قبل أي عملية await. وإلا فلن يمكن الوصول إلى الخصائص والدوال المعرّفة بعد عملية الـ await.
اطلع أيضًا على: إضافة الأنواع لمراجع مكونات القالب