جاوااسکریپت - چگونه میتوان useTemplateRefsList را بهطور صحیح در یک کامپوننت بازگشتی در Vue 3 تایپ کرد؟
من دارم روی یک کامپوننت بازگشتی Vue 3 با استفاده از Composition API و تابع useTemplateRefsList از @vueuse/core کار میکنم.
هدف من جمعآوری ارجاعات به هر نمونه از کامپوننت بازگشتی است. با این حال، من در تایپ صحیح لیست ارجاعات مشکل دارم، زیرا کلمه کلیدی this در API ترکیبی در دسترس نیست.
در اینجا یک نسخه سادهشده از تنظیمات من آمده است:
// toto.vue
<template>
{{ data.name }}
<toto
v-for="item in data.children"
ref="childRefs"
:key="item.id"
:data="item.children"
/>
</template>
<script setup lang="ts">
import { useTemplateRefsList } from '@vueuse/core';
const { data } = defineProps<{
id: string;
name: string;
children?: [
{
id: string;
name: string,
children?: [...]
}
]
}>();
// Attempting to type the refs list
const childRefs = useTemplateRefsList</* What type goes here? */>();
</script>
مشکل
من میخواهم childRefs را تایپ کنم به طوری که به درستی نمایانگر آرایهای از نمونههای مؤلفه بازگشتی باشد.
از آنجا که this در نحو تنظیم اسکریپت در دسترس نیست، نمیتوانم مستقیماً به نوع نمونهی کامپوننت ارجاع دهم.
چیزی که امتحان کردهام
- استفاده از
ComponentPublicInstance:
const refs = useTemplateRefsList<ComponentPublicInstance>();
اما این نوع خیلی کلی است و بازتابدهنده نمونه واقعی مؤلفه بازگشتی نیست.
- استفاده از
InstanceType:
const refs = useTemplateRefsList<InstanceType<typeof RecursiveComponent>>();
با این حال، RecursiveComponent هنوز در طول اعلان خودش تعریف نشده است، که باعث ایجاد مشکل وابستگی حلقوی میشود.
- تایپ از طریق
expose
من استفاده از defineExpose برای آشکار کردن ویژگیها/متدها و نوعسازی در برابر آنها را در نظر گرفتم، اما این برای یک کامپوننت بازگشتی ساده زیاد به نظر میرسد.
- صادرات نوع از فایل
tsدیگر
// definitionsFile.ts
import Toto from './Toto.vue';
// Without using an object, I get the following error: Type alias 'TotoType' circularly references itself.
export type TotoType = { a: InstanceType<typeof PermissionSummaryRow> };
// toto.vue
import Toto from './Toto.vue';
// 'childRefs' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer
const childRefs = useTemplateRefsList<TotoType['a']>();
// any
const test = childRefs.value[0]!;
سوال
راه صحیح تایپ کردن useTemplateRefsList برای یک کامپوننت بازگشتی در Vue 3 چیست؟ آیا راهی وجود دارد که بتوان نوع کامپوننت فعلی را به صورت پویا ارجاع داد، یا راه حلی وجود دارد تا به این هدف رسید؟
هر کمکی یا راهنماییای مورد قدردانی قرار خواهد گرفت!
پاسخ شماره ۱
با Vue 3.5+ شما میتوانید از useTemplateRef استفاده کنید که بهطور خودکار تایپ شده و استنتاج میشود.
با این حال یک ترفند وجود دارد. برای اینکه useTemplateRef بتواند کامپوننت فرزند بازگشتی را استنباط کند، آن را با نامی متفاوت وارد کنید، در غیر این صورت نمونه داخلی استنباط میشود، نه نمونهای که نمایش داده شده است:
زمین بازی
<script lang="ts" setup>
import CompChild from './Comp.vue';
type Item = {name: string, children?: Item[]};
defineProps<{
data: Item
}>();
import {ref} from 'vue';
import { useTemplateRef } from 'vue';
const $comps = useTemplateRef('$comps');
defineExpose({
addColor(){
color.value =
['red', 'green', 'lime', 'blue', 'orange', 'skyblue'][Math.random()* 6 | 0];
$comps.value?.forEach($comp => $comp.addColor());
}
});
const color = ref('inherit');
</script>
<template>
<div style="padding-left: 24px">
<div>{{ data.name }}</div>
<CompChild ref="$comps" v-if="data.children" v-for="item in data.children" :data="item"/>
</div>
</template>
<style scoped>
div{
background-color: v-bind(color);
}
</style>
