Lorsque vous travaillez avec des projets où SSR (Server Side Rendering) n'est pas utilisé ou qu'il n'est pas possible de l'implémenter, le problème se pose que certaines fonctions ou logiques sont écrites deux fois pour les éléments statiques qui impriment le backend et pour les composants qui rendent Vue.
Par exemple, nous devons implémenter un composant d'extrait de produit qui a un certain nombre d'exigences:
- Il peut être imprimé statiquement depuis le backend avec toutes les informations nécessaires pour le référencement et la logique.
- Il peut être utilisé comme un composant Vue standard, en passant des paramètres via v-bind, en attachant des événements de clic , etc.
- Il devrait afficher l'état actuel du bouton d'achat
- Après avoir cliqué sur le bouton «Acheter», un préchargeur devrait apparaître en attendant le statut du panier
Une solution:
- Écrivez la logique des extraits statiques en attachant des événements de clic, ajoutez et supprimez des classes de charge sur le bouton Acheter
- Écrire séparément un composant sur Vue qui implémente la même logique uniquement au format modèle
- Utilisez le premier élément pour sortir du backend, le second, par exemple, pour sortir des données propres obtenues à partir de state ou ajax
Ainsi nous écrirons deux logiques, l'une travaillera directement avec le DOM, l'autre avec des données pures.
Ma solution à ce problème consiste à utiliser des emplacements, à savoir la possibilité de définir le contenu par défaut, qui contiendra des paramètres dynamiques, mais en même temps, si le composant est utilisé comme un modèle en ligne, tous ces paramètres seront remplacés par ceux dessinés par le backend.
Écrivons un composant qui peut gérer à la fois la statique et la dynamique:
Liste des composants<template> <div> <slot name="image"> <a :href="url" class="snippet__image"> <img :src="image"> </a> </slot> <slot name="title"> <a :href="url" class="snippet__title">{{ title }}</a> </slot> <div v-if="!inCart" @click="add" :class="{ 'snippet__buy--load': load }" class="snippet__control" > <slot name="button"> <div class="snippet__button"></div> </slot> </div> <div v-if="inCart" class="snippet__control"> <div class="snippet__button"></div> </div> <div v-if="load" class="snippet__load"></div> </div> </template> <script>
Utilisation d'un composant via le backend:
<snippet :id="1" class="snippet"> <a slot="image" href="#" class="snippet__image"> <img src="photo.jpg"> </a> <a slot="title" href="#" class="snippet__title"> 1</a> <div slot="button" class="snippet__button"></div> </snippet>
Utilisation d'un composant dans d'autres composants:
<catalog-list> <snippet v-for="item in items" :key="item.id" v-bind="item"></snippet> </catalog-list>
Nous avons maintenant un composant qui peut être utilisé dans différents cas.
J'aimerais avoir votre avis sur cette approche, il y a peut-être une meilleure solution.