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.html
trouvé 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.js
composant 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é
el
pour organiser sa liaison à l'élément DOM. Dans le cas d'un composant, une propriété est utilisée template
qui 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
data
ce 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 data
s'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 data
pas 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
product
dans 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, ajoutons
index.html
quelques composants supplémentairesau codeproduct
. En fait, c'est ainsi que la réutilisation des composants est organisée. Le codeindex.html
ressemblera à 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 composant
product
, le codeindex.html
ressemblera 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
product
est 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
product
génère premium
diffé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'
premium
instance 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
props
dé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
premium
est Boolean
et 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é
premium
sur 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
product
sait 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
premium
composant. 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épremium
qui est stockée dans nos données d'instance Vue.
L'instance racine de Vue peut maintenant passer au
premium
composant enfantproduct
. Étant donné que l'attribut est lié à une propriété àpremium
partir des données d'instance Vue, la valeur actuellepremium
sera toujours transmise au composantproduct
.
L'image ci-dessus, à savoir l'inscription
User 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
Product
maintenant un paramètre d'entrée premium
qui 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 est
premium
défini sur une valeurtrue
, l'utilisateur a droit à la livraison gratuite. Créons une nouvelle propriété calculéeshipping
et utilisons le paramètre qu'elle contientpremium
:
shipping() {
if (this.premium) {
return "Free";
} else {
return 2.99
}
}
Si elle est
this.premium
stockée dans un paramètre true
, la propriété calculée shipping
retournera 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 qui
Shipping: Free
apparaît sur la page en raison du fait que le composant reçoit un paramètre d'entréepremium
dé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-details
qui doit utiliser un paramètre d'entrée details
et ê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