مراجع القالب
بينما يخفي نموذج التصيير التصريحي لـ Vue معظم عمليات DOM المباشرة بالنسبة لك، فقد يكون هناك حالات تحتاج فيها إلى الوصول المباشر إلى عناصر DOM الأساسية. للوصول إلى هذا، يمكننا استخدام السمة الخاصة ref
:
template
<input ref="input">
ref
هو سمة خاصة، مماثلة لسمة key
التي تم مناقشتها في محور v-for
. يسمح لنا بالحصول على مرجع مباشر لعنصر DOM محدد أو نسخة مكون ابن بعد وصله. قد يكون هذا مفيدًا عندما تريد، على سبيل المثال، التركيز برمجيًا على عنصر إدخال على مكون موصول بالـDOM أو تهيئة مكتبة طرف ثالث على عنصر معين. ref
هو سمة خاصة، مماثلة لسمة key
التي تم مناقشتها في محور v-for
. يسمح لنا بالحصول على مرجع مباشر لعنصر DOM محدد أو نسخة مكون ابن بعد وصله. قد يكون هذا مفيدًا عندما تريد، على سبيل المثال، التركيز برمجيًا على عنصر إدخال على مكون موصول بالـDOM أو تهيئة مكتبة طرف ثالث على عنصر معين.
الوصول إلى المراجع
To obtain the reference with Composition API, we can use the useTemplateRef()
helper:
vue
<script setup>
import { useTemplateRef, onMounted } from 'vue'
// the first argument must match the ref value in the template
const input = useTemplateRef('my-input')
onMounted(() => {
input.value.focus()
})
</script>
<template>
<input ref="my-input" />
</template>
When using TypeScript, Vue's IDE support and vue-tsc
will automatically infer the type of input.value
based on what element or component the matching ref
attribute is used on.
Usage before 3.5
In versions before 3.5 where useTemplateRef()
was not introduced, we need to declare a ref with a name that matches the template ref attribute's value:
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
}
}
}
Note that you can only access the ref after the component is mounted. If you try to access input
in a template expression, it will be null
on the first render. This is because the element doesn't exist until after the first render!
إذا كنت تحاول مراقبة تغييرات مرجع القالب، تأكد من إدراج الحالة حيث يكون مرجع القالب ذو قيمة معدومة null
:
js
watchEffect(() => {
if (input.value) {
input.value.focus()
} else {
// غير موصول بعد، أو العنصر أزيل (على سبيل المثال ،بواسطة v-if)
}
})
اطلع أيضًا على : إضافة الأنواع للمراجع
المراجع داخل حلقات v-for
Requires v3.5 or above
لما يُستخدم المرجع 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>
Usage before 3.5
In versions before 3.5 where useTemplateRef()
was not introduced, we need to declare a ref with a name that matches the template ref attribute's value. The ref should also contain an array value:
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 will hold an instance of <Child />
})
</script>
<template>
<Child ref="child" />
</template>
Usage before 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 }
(المراجع تُفك تلقائياً مثل المكونات العادية).
Note that defineExpose must be called before any await operation. Otherwise, properties and methods exposed after the await operation will not be accessible.
See also: Typing Component Template Refs