ارجاع از طریق تمپلیت - Template Refs
درحالیکه مدل رندر اعلامی Vue بیشتر عملیات های مرتبط با DOM را برای شما جدا میکند، در مواردی پیش میآید که نیاز داریم به المنت های DOM دسترسی مستقیم داشته باشیم. برای رسیدن به این هدف، میتوانیم از ویژگی به خصوص ref
بهره ببریم:
template
<input ref="input">
ویژگی ref
همانند ویژگی key
که در بخش v-for
مورد بحث قرار گرفت، یک ویژگی به خصوص است. این ویژگی به ما اجازه میدهد ارجاعی مستقیم، به المنت مشخصی از DOM یا کامپوننت فرزند بعد از اینکه در DOM قرار گرفت (mount شد) بدست بیاوریم. به عنوان مثال، این ویژگی ممکن است هنگامی مفید باشد که شما بخواهید توسط کد عمل فوکس را بر روی یک input درون کامپوننتی که مانت شده انجام دهید یا یک کتابخانه شخص ثالث را بر روی المنتی مقدار دهی اولیه کنید.
دسترسی به ارجاع
برای دسترسی به ارجاع در 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 و IDE پشتیبانی شده توسط Vue و vue-tsc
به طور خودکار تایپ inputRef.value
را بر اساس عنصر یا کامپوننت ای که ویژگی ref منطبق بر روی آن استفاده می شود، استنتاج می کند.
روش استفاده قبل از 3.5
در نسخههای قبل از 3.5 که در آن useTemplateRef()
معرفی نشده بود، نیاز داریم که یک ref هم نام با آن تعریف کنیم. نامی که با مقدار اتریبیوت ref در تمپلیت مطابقت دارد:
vue
<script setup>
import { ref, onMounted } from 'vue'
// برای نگهداری از ارجاع المنت تعریف کن ref یک
// باید با مقدار ارجاع تمپلیت یکسان باشد ref نام
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 شد میتوانید به ref دسترسی داشته باشید. اگر شما سعی کنید که به input
درون یک عبارت تمپلیت دسترسی داشته باشید، در اولین رندر مقدار null
را خواهد داشت. این به این دلیل است که المنت تا بعد از اولین رندر موجود نمیباشد.
اگر سعی داشته باشید که تغییرات ارجاع تمپلیت را watch کنید، اطمینان حاصل کنید در موردی که مقدار ارجاع null
است را نظر بگیرید :
js
watchEffect(() => {
if (input.value) {
input.value.focus()
} else {
// (v-if برای مثال توسط) قرار دارد unmounted نشده یا در حالت mount المنت هنوز
}
})
همچنین ببینید: Typing Template Refs
استفاده از ارجاعها درون v-for
به نسخه v3.2.25 یا بالاتر نیاز دارد
هنگامی که ref
درون v-for
استفاده میشود، ارجاع مربوطه باید شامل مقدار آرایه باشد، که این آرایه بعد از عمل mount با المنتها پُر میشود.
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>
آن را در Playground امتحان کنید
روش استفاده قبل از 3.5
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) => { /* اختصاص دهید ref را به یک پراپرتی یا el */ }">
توجه داشته باشید ما داریم از یک اتصال :ref
پویا استفاده میکنیم تا بتوانیم یک تابع را به جای یک رشته برای نام ارجاع ارسال کنیم. هنگامی که المنت unmounted میشود، آرگومان null
خواهد بود. البته که شما میتوانید از یک متد به جای تابع خطی استفاده کنید.
استفاده از ارجاع در کامپوننت
این قسمت دانش Components را فرض میکند. راحت از آن صرف نظر کنید و بعداً برگردید.
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 /> نمونهای از child.value
})
</script>
<template>
<Child ref="child" />
</template>
اگر کامپوننت فرزند از Options API استفاده میکند یا از <script setup>
استفاده نمیکند، نمونه دریافت شده از ارجاع با کلمه کلیدی this
کامپوننت فرزند یکسان خواهد بود، این به این معنی است که کامپوننت والد به هر پراپرتی و متد کامپوننت فرزند دسترسی خواهد داشت. این کار را آسان میکند که جزئیات پیاده سازی کاملا محکمی بین کامپوننت والد و فرزند ایجاد شود، بنابراین میتوان از ارجاع کامپوننتها در صورت لزوم استفاده کرد - در بیشتر موارد، ابتدا باید سعی کنید که تعاملات بین والد و فرزند را با استفاده از رابط های props و emit به کار ببرید.
یک استثنا در اینجا وجود دارد، کامپوننتهایی که از <script setup>
استفاده میکنند به صورت پیشفرض خصوصی هستند: کامپوننت والدی که با استفاده از <script setup>
به کامپوننت فرزند رجوع میکند قادر نخواهد بود به چیزی دسترسی پیدا کند مگر اینکه کامپوننت فرزند با استفاده از ماکرو defineExpose
یک رابط عمومی را در معرض دید قرار دهد:
vue
<script setup>
import { ref } from 'vue'
const a = 1
const b = ref(2)
// نیاز به ایمپورت شدن ندارند defineExpose ماکروهای کامپایلر، مانند
defineExpose({
a,
b
})
</script>
هنگامی که والد نمونهای از این کامپوننت را از طریق ارجاع تمپلیت میگیرد، نمونه بازیابی شده به شکل { a: number, b: number }
خواهد بود (refها همانند نمونههای معمولی به صورت خودکار unwrap میشوند)
همچنین ببینید: Typing Component Template Refs