Skip to content

مراجع القالب

بينما يخفي نموذج التصيير التصريحي لـ 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
    }
  }
}

المرجع الناتج سيُعرض على this.$refs:

vue
<script>
export default {
  mounted() {
    this.$refs.input.focus()
  }
}
</script>

<template>
  <input ref="input" />
</template>

Note that you can only access the ref after the component is mounted. If you try to access $refs.inputinput in a template expression, it will be undefinednull 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>

Try it in the Playground

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 داخل v-for، يجب أن يحتوي المرجع المقابل على قيمة مصفوفة :

vue
<script>
export default {
  data() {
    return {
      list: [
        /* ... */
      ]
    }
  },
  mounted() {
    console.log(this.$refs.items)
  }
}
</script>

<template>
  <ul>
    <li v-for="item in list" ref="items">
      {{ 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>
vue
<script>
import Child from './Child.vue'

export default {
  components: {
    Child
  },
  mounted() {
    // this.$refs.child سيحتوي على نسخة من  <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

خيار expose يمكن استخدامه لتقييد الوصول إلى نسخة المكون الابن:

js
export default {
  expose: ['publicData', 'publicMethod'],
  data() {
    return {
      publicData: 'foo',
      privateData: 'bar'
    }
  },
  methods: {
    publicMethod() {
      /* ... */
    },
    privateMethod() {
      /* ... */
    }
  }
}

في المثال أعلاه، سيكون للمكون الأب الحق في الوصول إلى publicData و publicMethod فقط.

مراجع القالب has loaded