Emplacements de portée Vue 3/Nuxt 3 avec des types de données génériques déduits des accessoires
P粉863295057
P粉863295057 2023-11-02 21:59:05
0
1
734

Je souhaite implémenter un composant carrousel dans Nuxt v3. Ce composant reçoit une liste d'éléments. Ce composant implémente uniquement la logique, pas le style ou la structure.

Maintenant, voici mon composant :

组件/tdx/carousel.vue

<template>
  <div>
    <slot name="last"></slot>
    <div v-for="item in items">
      <slot
        name="item"
        v-bind="item"
      ></slot>
    </div>
    <slot name="next"></slot>
  </div>
</template>

<script setup lang="ts">
const props = defineProps({
  items: {
    type: [],
    required: true,
  },
  spotlight: {
    type: Number,
    default: 1,
    validator(value: number) {
      return value > 0;
    },
  },
});
</script>

La logique du carrousel n'est pas importante ici.

Dans le composant parent, je peux utiliser le composant comme ceci :

<template>
  <div class="container">
    <TdxCarousel :items="exampleArray">
      <template #item="{ title, description }">
        <p class="font-semibold text-2xl">{{ title }}</p>
        <hr />
        <p>{{ description }}</p>
      </template>
    </TdxCarousel>
  </div>
</template>

<script setup lang="ts">
const exampleArray = ref([
  {
    title: 'Item 1',
    description: 'Desc of item 1',
  },
  {
    title: 'Item 2',
    description: 'Desc of item 2',
  },
]);
</script>

Cela fonctionne très bien. A part ça, ce que je veux, c'est taper. titledescription 的类型当然是any,因为在 carousel.vue 的 props 中,项目的类型是 unknown[].

J'ai trouvé cet article montrant comment créer un composant générique, mais je ne veux pas de cela car je dois jouer avec le système d'importation automatique de nuxt.

Comment implémenter l'inférence de type à partir d'un élément donné dans l'attribut carousel.vue ?

P粉863295057
P粉863295057

répondre à tous(1)
P粉476547076

Mise à jour : mai 2023

À partir de Vue 3.3, prend officiellement en charge les composants universels.

Vous devez définir un paramètre commun. Modifiez la méthode de carousel.vue 组件以使用 标记中的 generic 属性,并将其转换为使用基于类型的defineProps pour qu'elle obtienne correctement les génériques.

<script setup lang="ts" generic="T extends any">
withDefaults(
  defineProps<{ items: T[]; spotlight?: number }>(), {
  spotlight: 1,
});
</script>
<template>
  <div>
    <slot name="last"></slot>
    <div v-for="item in items">
      <slot
        name="item"
        v-bind="item">
      </slot>
    </div>
    <slot name="next"></slot>
  </div>
</template>

Les accessoires sur les emplacements seront désormais correctement déduits en fonction du type d'élément.

Avant mai 2023

Dans les versions antérieures de VSCode/Volar, vous deviez activer le Drapeau expérimental. Il doit être dans l'option vueCompilerOptions 下启用 tsconfig.json 的 experimentalRfc436.

// tsconfig.json
{
  // ...
  "vueCompilerOptions": {
    "experimentalRfc436": true
  }
}

Ceci n'est plus nécessaire car il est activé par défaut dans les dernières versions de Volar.

Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal