Vue.js pour les débutants, leçon 8: composants

Aujourd'hui, dans la huitième leçon du cours Vue, vous aurez votre première exposition aux composants. Les composants sont des blocs de code réutilisables qui peuvent inclure à la fois l'aspect et la convivialité de certaines parties de l'application et la mise en œuvre des fonctionnalités du projet. Ils aident les programmeurs à créer une base de code modulaire facile à maintenir. Vue.js pour les débutants Leçon 1: Instance de VueVue.js pour les débutants, Leçon 2: Liaison d'attributsVue.js pour les débutants, Leçon 3: Rendu conditionnelVue.js pour les débutants, Leçon 4: Listes de renduVue .js pour les débutants, leçon 5: gestion des événementsVue.js pour les débutants, leçon 6: classes et styles de liaison



















Vue.js pour les débutants, leçon 7: propriétés calculées

Vue.js pour les débutants, leçon 8: composants



Le but de la leçon



L'objectif principal de cette leçon est de créer notre premier composant et d'explorer les mécanismes de transmission des données aux composants.



Code initial



Voici le code de fichier index.htmltrouvé dans la balise avec laquelle <body>nous allons commencer:



<div id="app">
  <div class="product">
    <div class="product-image">
      <img :src="image" />
    </div>

    <div class="product-info">
      <h1>{{ title }}</h1>
      <p v-if="inStock">In stock</p>
      <p v-else>Out of Stock</p>
      <p>Shipping: {{ shipping }}</p>

      <ul>
        <li v-for="detail in details">{{ detail }}</li>
      </ul>
      <div
        class="color-box"
        v-for="(variant, index) in variants"
        :key="variant.variantId"
        :style="{ backgroundColor: variant.variantColor }"
        @mouseover="updateProduct(index)"
      ></div>

      <button
        v-on:click="addToCart"
        :disabled="!inStock"
        :class="{ disabledButton: !inStock }"
      >
        Add to cart
      </button>

      <div class="cart">
        <p>Cart({{ cart }})</p>
      </div>
    </div>
  </div>
</div>


Voici le code main.js:



var app = new Vue({
  el: '#app',
  data: {
    product: 'Socks',
    brand: 'Vue Mastery',
    selectedVariant: 0,
    details: ['80% cotton', '20% polyester', 'Gender-neutral'],
    variants: [
      {
        variantId: 2234,
        variantColor: 'green',
        variantImage: './assets/vmSocks-green.jpg',
        variantQuantity: 10
      },
      {
        variantId: 2235,
        variantColor: 'blue',
        variantImage: './assets/vmSocks-blue.jpg',
        variantQuantity: 0
      }
    ],
    cart: 0,
  },
  methods: {
    addToCart() {
      this.cart += 1;
    },
    updateProduct(index) {
      this.selectedVariant = index;
      console.log(index);
    }
  },
  computed: {
    title() {
      return this.brand + ' ' + this.product;
    },
    image() {
      return this.variants[this.selectedVariant].variantImage;
    },
    inStock(){
      return this.variants[this.selectedVariant].variantQuantity;
    }
  }
})


Tâche



Nous n'avons pas besoin que toutes les données, méthodes, propriétés calculées dans l'application Vue soient localisées dans l'instance racine de Vue. Au fil du temps, cela conduira à un code qui sera très difficile à maintenir. Au lieu de cela, nous aimerions diviser le code en morceaux modulaires qui sont plus faciles à utiliser et qui rendent le développement plus flexible.



La solution du problème



Commençons par prendre le code existant et le déplacer dans un nouveau composant.



Voici comment le main.jscomposant est enregistré dans le fichier :



Vue.component('product', {})


Le premier argument est le nom du composant de notre choix. Le second est un objet d'options similaire à celui que nous avons utilisé pour instancier Vue dans les tutoriels précédents.



Dans l'instance Vue, nous avons utilisé une propriété elpour organiser sa liaison à l'élément DOM. Dans le cas d'un composant, une propriété est utilisée templatequi définit le code HTML du composant.



Décrivons le modèle de composant dans un objet avec des options:



Vue.component('product', {
  template: `
    <div class="product">
… //    HTML-,        product
    </div>
  `
})


Il existe plusieurs façons de créer des modèles dans Vue. Nous utilisons maintenant un modèle littéral, dont le contenu est placé entre guillemets.



S'il s'avère que le code du modèle ne sera pas placé dans un seul élément racine, tel qu'un élément <div>avec une classe product, cela entraînera le message d'erreur suivant:



Component template should contain exactly one root element


En d'autres termes, un modèle de composant ne peut renvoyer qu'un seul élément.



Par exemple, le modèle suivant est bien formé car il n'est représenté que par un seul élément:



Vue.component('product', {
  template: `<h1>I'm a single element!</h1>`
})


Mais si le modèle contient plusieurs frères et sœurs, cela ne fonctionnera pas. Voici un exemple de mauvais modèle:



Vue.component('product', {
  template: `
    <h1>I'm a single element!</h1>
    <h2>Not anymore</h2>
    `
})


En conséquence, il s'avère que si un modèle doit inclure de nombreux éléments, par exemple un ensemble d'éléments inclus dans notre <div>classe product, ces éléments doivent être placés dans un élément de conteneur externe. En conséquence, le modèle n'aura qu'un seul élément racine.



Maintenant que le modèle contient le code HTML qui se trouvait auparavant dans le fichier index.html, nous pouvons ajouter des données, des méthodes, des propriétés calculées au composant qui étaient auparavant dans l'instance racine de Vue:



Vue.component('product', {
  template: `
  <div class="product">
…
  </div>
  `,
  data() {
    return {
      //   
    }
  },
    methods: {
      //   
    },
    computed: {
      //    
    }
})


Comme vous pouvez le voir, la structure de ce composant est presque exactement la même que la structure de l'instance Vue avec laquelle nous avons travaillé précédemment. Avez-vous remarqué que datace n'est plus une propriété, mais une méthode d'un objet avec des options? Pourquoi cela est-il ainsi?



Le fait est que les composants sont souvent créés avec des plans pour les réutiliser. Si nous avons de nombreux composants product, nous devons nous assurer que chacun d'eux a ses propres instances d'entité data. Puisqu'il datas'agit désormais d'une fonction qui renvoie un objet avec des données, chaque composant est assuré de recevoir son propre ensemble de données. Si l'entité n'était datapas une fonction, alors chaque composantproduct, partout où de tels composants étaient utilisés, contiendraient les mêmes données. Cela va à l'encontre de l'idée de composants réutilisables.



Maintenant que nous avons déplacé le code lié au produit dans un composant natif product, le code pour décrire l'instance racine de Vue ressemble à ceci:



var app = new Vue({
  el: '#app'
})


Il ne nous reste plus qu'à placer le composant productdans le code du fichier index.html. Il ressemblera à ceci:



<div id="app">
  <product></product>
</div>


Si vous rechargez la page d'application maintenant, elle reviendra à sa forme précédente.





Page Application



Si vous regardez maintenant dans les outils de développement Vue, vous remarquerez qu'il existe une entité racine et un composant Produit.





Analyse de l'application avec les outils de développement Vue



Maintenant, juste pour démontrer la réutilisabilité des composants, ajoutonsindex.htmlquelques composants supplémentairesau codeproduct. En fait, c'est ainsi que la réutilisation des composants est organisée. Le codeindex.htmlressemblera à ceci:



<div id="app">
  <product></product>
  <product></product>
  <product></product>
</div>


Et la page affichera trois copies de la fiche produit.





Plusieurs fiches produits affichées sur une page



Veuillez noter qu'à l'avenir, nous travaillerons avec un composantproduct, le codeindex.htmlressemblera donc à ceci:



<div id="app">
  <product></product>
</div>


Tâche



Les applications ont souvent besoin de composants pour accepter les données, les paramètres d'entrée, des entités parentes. Dans ce cas, le parent du composant productest l'instance racine de Vue elle-même.



Laissez l'instance racine de Vue avoir une description de certaines données. Ces données indiquent si l'utilisateur est titulaire d'un compte premium. Le code pour décrire une instance de Vue pourrait ressembler à ceci:



var app = new Vue({
  el: '#app',
  data: {
    premium: true
  }
})


Décidons que les utilisateurs premium ont droit à la livraison gratuite.



Cela signifie que nous voulons que le composant productgénère premiumdifférentes informations sur les frais d'expédition en fonction de ce qui est écrit dans la propriété d' instance racine de Vue.



Comment puis-je envoyer les données stockées dans la propriété d' premiuminstance racine Vue à l' enfant qui est le composant product?



La solution du problème



Dans Vue, pour transférer des données d'entités parentes vers des enfants, une propriété d'objet avec des options propsdécrites par les composants est utilisée. Il s'agit d'un objet avec une description des paramètres d'entrée du composant, dont les valeurs doivent être définies en fonction des données reçues de l'entité parente.



Commençons par décrire le type de paramètres d'entrée que le composant s'attend à recevoir product. Pour ce faire, ajoutez la propriété correspondante à l'objet avec les options utilisées lors de sa création:



Vue.component('product', {
  props: {
    premium: {
      type: Boolean,
      required: true
    }
  },
  //    , ,  
})


Notez que cela utilise la capacité intégrée de Vue à valider les paramètres passés à un composant. A savoir, nous indiquons ce que le type du paramètre d'entrée premiumest Booleanet ce que ce paramètre est requis par la mise requiredà true.



Ensuite, modifions le modèle qui affiche les paramètres passés à l'objet. En affichant la valeur de la propriété premiumsur la page, nous nous assurerons que le mécanisme que nous étudions fonctionne correctement.



<p>User is premium: {{ premium }}</p>


Jusqu'à présent, tout va bien. Le composant productsait qu'il recevra le paramètre de type requis pour son fonctionnement Boolean. Nous avons préparé un endroit pour afficher les données pertinentes.



Mais nous n'avons pas encore transmis le paramètre au premiumcomposant. Vous pouvez le faire en utilisant un attribut personnalisé similaire à la «ligne» qui mène à un composant à travers lequel il est possible de transmettre les paramètres d'entrée, et en particulier premium.



Modifions le code dans index.html:



<div id="app">
  <product :premium="premium"></product>
</div>


Rafraîchissons la page.





Sortie des données transmises au composant



Les paramètres d'entrée sont désormais transmis au composant. Parlons exactement de ce que nous venons de faire.



Nous transmettons au composant un paramètre d'entrée, ou "attribut personnalisé" appelépremium. Nous lions cet attribut personnalisé à l'aide de la construction deux-points à une propriétépremiumqui est stockée dans nos données d'instance Vue.



L'instance racine de Vue peut maintenant passer aupremiumcomposant enfantproduct. Étant donné que l'attribut est lié à une propriété àpremiumpartir des données d'instance Vue, la valeur actuellepremiumsera toujours transmise au composantproduct.



L'image ci-dessus, à savoir l'inscriptionUser is premium: true, prouve que tout a été fait correctement.



Nous avons maintenant vérifié que le mécanisme de transfert de données que nous étudions fonctionne comme prévu. Si vous regardez dans les outils de développement Vue, il s'avère que le composant a Productmaintenant un paramètre d'entrée premiumqui stocke une valeur true.





Paramètre d'entrée du composant



Maintenant que les données indiquant si l'utilisateur possède un compte premium entre dans le composant, utilisons ces données pour afficher les informations de frais de port sur la page. N'oublions pas que si le paramètre estpremiumdéfini sur une valeurtrue, l'utilisateur a droit à la livraison gratuite. Créons une nouvelle propriété calculéeshippinget utilisons le paramètre qu'elle contientpremium:



shipping() {
  if (this.premium) {
    return "Free";
  } else {
    return 2.99
  }
}


Si elle est this.premiumstockée dans un paramètre true, la propriété calculée shippingretournera Free. Sinon, il reviendra 2.99.



Supprimons le code de sortie de la valeur de paramètre du modèle de composant premium. Maintenant, l'élément <p>Shipping: {{ shipping }}</p>qui était présent dans le code avec lequel nous avons commencé aujourd'hui pourra afficher des informations sur les frais de port.





Les utilisateurs Premium reçoivent un



texte de livraison gratuit quiShipping: Free apparaît sur la page en raison du fait que le composant reçoit un paramètre d'entréepremiumdéfini sur une valeurtrue.



Merveilleux! Nous avons maintenant appris à transférer des données d'entités mères vers des enfants et avons pu utiliser ces données dans le composant pour gérer le coût d'expédition des marchandises.



À propos, il convient de noter que vous ne devez pas modifier leurs paramètres d'entrée dans les composants enfants.



Atelier



Créez un nouveau composant product-detailsqui doit utiliser un paramètre d'entrée detailset être responsable du rendu de la partie de la fiche produit qui a été précédemment formée à l'aide du code suivant:



<ul>
  <li v-for="detail in details">{{ detail }}</li>
</ul>


Voici un modèle que vous pouvez utiliser pour résoudre ce problème.



Voici la solution au problème.



Résultat



Aujourd'hui était votre première introduction aux composants Vue. Voici ce que vous avez appris:



  • Les composants sont des blocs de code présentés sous forme d'éléments personnalisés.
  • Les composants facilitent la gestion de votre application en la décomposant en éléments réutilisables. Ils contiennent des descriptions du composant visuel et des fonctionnalités de la partie correspondante de l'application.
  • Les données de composant sont représentées par une méthode d'un data()objet avec des options.
  • Les paramètres d'entrée ( props) sont utilisés pour transmettre les données des entités parentes aux entités enfants .
  • Nous pouvons décrire les exigences pour les paramètres d'entrée que le composant prend.
  • .
  • .
  • Vue .




Utilisez-vous les outils de développement Vue?



Vue.js débutants leçon 1: instance Vue

Vue.js pour les débutants, leçon 2: attributs de liaison

Vue.js débutants leçon 3: rendu conditionnel

Vue.js débutants leçon 4: rendu des listes

Vue .js pour les débutants leçon 5: traitement des événements

Vue.js pour débutants leçon 6: lier les classes et les styles

Vue.js pour débutants leçon 7: propriétés calculées

Vue.js pour débutants leçon 8: composants






All Articles