Fermer

décembre 1, 2021

« defineComponent » dans Vue 3 est de la pure magie !


Je suis sûr que vous avez déjà vu que defineComponent est le mot clé pour TypeScript dans Vue 3, mais savez-vous comment cela fonctionne ? Jetons un coup d'œil derrière le rideau et voyons où la magie opère !

Imaginez la situation : c'est la fin d'une longue journée de codage et toute votre logique fonctionne parfaitement, comme une toute nouvelle Ferrari avec un moteur V12 et seulement 4 milles dessus. Mais, il y a toujours cette méchante erreur TypeScript qui ne veut pas disparaître, et elle casse la construction, peu importe ce que vous essayez ! J'y suis allé, et si vous avez ressenti cela aussi, veuillez accepter ce câlin de ma part. Il y avait de nombreux cas manquants et de nombreuses solutions de contournement piratées. Dans Vue 3, d'autre part, nous avons l'incroyable méthode defineComponent qui permet de déplacer très facilement des projets existants vers TypeScript, si facilement que même votre chat pourrait le faire pour vous.

cat in lunettes assises devant un ordinateur

Vers TypeScript ou pas ?

Que vous aimiez ou non TypeScript, je vais essayer de vous convaincre qu'il s'agit de l'une des plus grandes nouveautés de Vue 3. Sa superpuissance est pour vous faire gagner du temps en détectant les erreurs et en fournissant des correctifs avant d'exécuter le code. Cela signifie en fait que vous testez pendant le codage.

Cela permet également d'utiliser instantanément de nombreux outils qui peuvent augmenter la productivité, comme VueDXVetur ou l'incroyable Volar par exemple. Une fois que vous l'aurez configuré, vous pourrez utiliser toutes sortes d'autocomplétions de modules, de configurations globales de composants et de correctifs rapides, et tout cela sera réalisé sans même avoir besoin de construire notre projet.

Je vais essayer de révéler toutes les informations que j'ai trouvées sur TypeScript dans Vue 3 dans les lignes ci-dessous – vous pouvez donc vous sentir beaucoup plus familier avec lui et le considérer comme une option lors du démarrage d'un nouveau projet Vue CLI.

Quelle est l'idée principale derrière cela. ?

Si vous jetez un œil à la documentation officielle de Vue 3vous remarquerez qu'il existe de nombreux exemples qui expliquent comment utiliser TypeScript dans de nombreux scénarios différents. La partie la plus intéressante est que pour que tout cela fonctionne, vous n'avez pas à vous rappeler d'inclure différents types d'interfaces pour le composant. Tout ce que vous avez à faire est d'envelopper l'objet du paramètre de composant dans une fonction defineComponent. Avoir cette option offre la possibilité d'adopter instantanément TypeScript dans des projets de base de code encore plus grands.

C'est exactement l'approche qui continue de prouver que Vue est le framework JavaScript le plus simple pour démarrer, n'est-ce pas ? Faire sans 'defineComponent'?

Si nous devions ajouter les types sans la fonction defineComponentnous aurions besoin d'ajouter une combinaison compliquée d'interfaces avant chacun de nos composants en fonction de son contenu, comme c'est le cas fait dans l'exemple imaginaire dans le code ci-dessous :

const myComponent : DefineComponent<

  PropsOrPropOptions = {},

  RawBindings = {},

  D = {},

  [19659017]C étend ComputedOptions = ComputedOptions,

  M e xtends MethodOptions = MethodOptions,

  Mixin extend ComponentOptionsMixin = ComponentOptionsMixin,

  Extendin = ComponentOptionsMixin,

  E étend EmitsOptions = Record,

  EE étend chaîne = chaîne,

  PP = PublicProps,

  Props = Lecture seule<ExtractPropTypes>,

  Defaults = ExtractDefaultPropTypes

= {[19659002]

}

Ce n'était pas un joli code pour un usage quotidien, n'est-ce pas ? C'est exactement l'une des raisons pour lesquelles la communauté anti-TypeScript existe. Non seulement cela, mais nous devrions toujours choisir une déclaration d'interface différente pour chaque composant en fonction des cinq cas de déclaration Vue importants suivants. Si c'est :

  1. Une fonction de configuration
  2. Un format d'objet sans accessoires
  3. Un format d'objet avec un tableau d'accessoires
  4. Un format d'objet avec des accessoires d'objet
  5. Une définition d'option personnalisée

Cela ferait être une expérience horrible, n'est-ce pas !? Et c'est exactement pourquoi defineComponent est ici !

Comment est-il implémenté ?

Les concepts derrière defineComponent nous ramènent aux racines de JavaScript : les fonctions pures et Surcharge de la fonction TypeScript. Pour faciliter la tâche des utilisateurs, toute la logique est cachée derrière un seul nom : defineComponent.

Nous passons toujours n'importe quel objet et renvoyons l'objet correctement tapé. Tous les cas des différents objets qui pourraient créer un composant Vue sont traités dans des surcharges distinctes. Le code exact de son implémentation peut être trouvé dans le référentiel GitHub icimais je vais essayer d'expliquer chaque surcharge ci-dessous :

Si vous n'êtes pas familiarisé avec les surcharges de fonctions, considérez-les comme de nombreuses fonctions avec le même nom, juste des paramètres différents (par numéro ou par type) qui ont toujours le même type de retour.

La première surcharge traite du cas où nous créons le composant à partir d'une fonction de configuration :

// surcharge 1 : fonction de configuration directe

defineComponent({

    setup (props, ctx) {

    retour {…}

}

});

Le deuxième cas est le cas lorsque les accessoires sont définis comme un objet vide :

// surcharge 2 : format d'objet sans accessoires

defineComponent({

    props : {},

    

});

Le troisième cas est le cas lorsque les props du composant sont définis comme un tableau de chaînes et que defineComponent attend des props comme interface d'une collection —Lecture seule<{ [key in PropNames]?: any }>. Voici à quoi cela devrait ressembler :

// surcharge 3 : format d'objet avec déclaration d'accessoires de tableau

defineComponent({

props : ['postTitle'],

});

Le quatrième est le cas lorsque les accessoires sont définis comme un tableau de chaînes et la fonction attend des accessoires de type PropsOptions s'étend en lecture seulecomme indiqué ci-dessous :

overload 4: object format with object props declaration

defineComponent({

props : {

  title : String,

  j'aime : Numéro

}

…[19659043]L'option « dernière mais non la moindre » consiste à passer un objet t ou type inconnu ou un objet avec une configuration et un nom définis :

// implémentation, proche de no-op

defineComponent({

configuration : fonction

nom : 'un nom'

});

Comme vous voyez, tous ces cas sont responsables de différents scénarios, mais le type de retour est toujours le même : une interface defineComponent avec tous les types que vous devez appliquer pour les accessoires, les données et les autres paramètres nécessaires pour le composant. Encore une autre preuve que les meilleures solutions sont généralement les plus simples.

Deeper Precision

L'utilisation de defineComponent est extrêmement utile et vous permet de saisir votre projet et de rejoindre les forces obscures du monde TypeScript— pourtant, si vous voulez avoir des types corrects sur toutes les propriétés qui pourraient être utilisées dans le composant, vous devrez peut-être ajouter un peu plus d'amour. temps à comment ajouter correctement des types dans un composant Vue :

export default defineComponent({

  name : 'TypescriptExamples'[19659078],

  accessoires : {

    nom : {

      type : Chaîne,

      obligatoire : [19659084]vrai

    },

    id : [Number, String],

    succès : { type : chaîne },

    rappel : {

      type : Fonction comme PropType<() => void>

    },[19659002]    livre : {

      type : objet comme PropType,

      requis : vrai

    },

[    19659058]métadonnées : {

      type : null // m etadata est tapé comme any

    },

    bookA : {

      type : objet comme PropType,

      // Assurez-vous d'utiliser les fonctions de flèche

      default : () => ({

        titre : [19659077]'expression de fonction de flèche'

      }),

      validateur : (livre : Livre) => !!book.title

    },

    livreB : {

      type : objet comme PropType,

      // Ou indiquez explicitement ce paramètre

      default(this[19659078]: void) {

        return {

           titre : ]'Expression de fonction'

        }

      },

      validator(this: void, book: Book) {

        retour[196590]!!book.title

      }

    }

  },

  [19659017]setup(props) {

    const result = props.name.split('') // correct, 'nom' est saisi sous forme de chaîne

    const year = ref(2020)

    [19659058]const yearsplit = year.value.split('')// => La propriété 'split' n'existe pas sur le type 'number'

    const stringNumberYear = ref('2020') // année type : Ref

 [19659002]    stringNumberYear.value = 2020 // ok!

    const modal = ref<InstanceType< typeof MyModal>>()

    const openModal = () => {

      modal.value?.open()

    }

    const book = reactive({ title : 'Vue 3 Guide' })

    [19659241]// ou

    const book1 : Book = reactive({ title : 'Vue 3 Guide' })

    // ​​ou

    const book2 = reactive({ title : 'Vue 3 Guide' }) as Book

 

    const handleChange = (evt: Event) => {[19659002]      console.log((evt.target as HTMLInputElement).value)

    }

    retour {

      modal, openModal,

      livre, livre1, livre2,

      handleChange

    } ;

},

   émet : {

    addBook(charge utile : { bookName : string }) {

      // effectuer la validation d'exécution

      return payload.bookName.length > 0

     }

  },

  méthodes : {

    onSubmit() {

      [19659158]this.$emit('addBook'{

        bookName : '123'

     //   bookName : 123 // Tapez une erreur !

      })

 

    //  this.$emit('non-declared-event') // Erreur de saisie !

    }

  }

Écrire des tests avec Typescript comme un pro

Ma partie préférée sur l'utilisation de defineComponent et TypeScript dans Vue 3 ajoute des tests au projet. C'est un véritable changement de jeu dans ce domaine et rend même le processus agréable car il fournit ces impressionnants autocomplétions qui aident à couvrir tous les cas d'utilisation lors de l'écriture de tests.

Mieux encore, TypeScript réduit également le nombre total de tests nécessaires car les types vérifient la plupart des configurations possibles de manière statique.

Voici un exemple à quoi ressemblerait un processus d'écriture de test simple lorsque nous voulons tester un simple composant Vue 3 avec une Kendo Native Grid dans it.

testtypescript" title="testtypescript" style="vertical-align: middle;"/></p data-recalc-dims=

Et voici le code :

it('Kendo Grid rend 1 élément '() => {

   const wrapper1 = mount(Grid, {

     [19659319]props : {

         dataItems : [{

           Id:1,

           Produit : 'jouet'

[1945199018]] }]

      },

       

   })

   expect(wrapper1.findAll('.k-master-row'). longueur).toBe(1)

})

 

it('Kendo Grid rend 2 éléments'() => {

   const wrapper1 = monter (Grid, {

     props : {

          dataItems : [{

           Id:1,

            Produit : [1965199057]'''

         },

         {

{

[1945199018] ]           Id :2,

           Produit : 'car'

[  1990] 19659321]}]

      },

       

   })

   expect(wrapper1.findAll('.k-master-row').length ).toBe(2)

})

Vous pouvez consulter d'autres exemples similaires avec tous les composants Kendo UI pour Vue dans notre référentiel ici.

Mon prochain blog couvrira les techniques de gestion d'état lors de l'édition d'éléments Grid, alors restez à l'écoute pour cela.

Utiliserez-vous TypeScript dans Vue ?

Maintenant que vous avez lu tout cela, vous pouvez décider si l'utilisation de TypeScript dans votre projet Vue actuel vous convient. Personnellement, je sais déjà que je me lance !

Merci d'avoir lu jusqu'ici ! Pour plus de conseils sur Vue ou sur l'interface utilisateur Kendo pour les actualités de Vue, suivez-moi sur Twitter à l'adresse @pa4oZdravkov.

Bon codage TypeScript et Vue !




Source link