→ Vue.js pour les débutants Leçon 1: Instance de Vue
→ Vue.js pour les débutants, Leçon 2: Liaison d'attributs
→ Vue.js pour les débutants, Leçon 3: Rendu conditionnel
→ Vue.js pour les débutants, Leçon 4: Listes de rendu
→ 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
→ Vue. js pour les débutants leçon 9: événements personnalisés
Le but de la leçon
Nous allons créer un formulaire permettant aux visiteurs du site de soumettre des avis sur les produits. Dans le même temps, il est nécessaire que la révision ne puisse être envoyée que si tous les champs du formulaire sont remplis, ce qui doit être rempli.
Code initial
Voici ce qu'il y a maintenant
index.html
:
<div id="app">
<div class="cart">
<p>Cart({{ cart.length }})</p>
</div>
<product :premium="premium" @add-to-cart="updateCart"></product>
</div>
Cela ressemble à ceci
main.js
:
Vue.component('product', {
props: {
premium: {
type: Boolean,
required: true
}
},
template: `
<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>
</div>
`,
data() {
return {
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
}
]
}
},
methods: {
addToCart() {
this.$emit('add-to-cart', this.variants[this.selectedVariant].variantId);
},
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;
},
shipping() {
if (this.premium) {
return "Free";
} else {
return 2.99
}
}
}
})
var app = new Vue({
el: '#app',
data: {
premium: true,
cart: []
},
methods: {
updateCart(id) {
this.cart.push(id);
}
}
})
Tâche
Nous voulons que les visiteurs du site puissent laisser des avis sur les produits, mais notre site n'a pas encore les moyens de recevoir des données des utilisateurs. Les formulaires sont de tels moyens.
La solution du problème
Pour résoudre la tâche qui nous attend, nous devons créer un formulaire. Commençons par créer un nouveau composant spécifiquement pour travailler avec un formulaire. Appelons ce composant
product-review
. Ce nom a été choisi car le composant prendra en charge le formulaire de collecte des avis sur les produits. Le composant product-review
sera imbriqué dans le composant product
.
Enregistrons un nouveau composant, commençons à former son modèle et équipons-le de quelques données:
Vue.component('product-review', {
template: `
<input>
`,
data() {
return {
name: null
}
}
})
Comme vous pouvez le voir, il y a un élément dans le modèle de composant
<input>
, et il y a une propriété dans les données du composant data
, alors qu'il est vide.
Comment lier ce que l'utilisateur entre dans un champ à une propriété
name
?
Dans les leçons précédentes, nous avons parlé de la liaison de données à l'aide de directives
v-bind
, mais nous n'avons considéré que la liaison unidirectionnelle. Le flux de données est passé de la propriété qui stocke les données au contrôle qui les rend. Et maintenant, nous avons besoin que ce que l'utilisateur entre dans le champ apparaisse dans la propriété name
stockée dans les données du composant. En d'autres termes, nous voulons que le flux de données soit dirigé du champ d'entrée vers la propriété.
Directive modèle V
La directive
v-model
permet d'organiser la liaison de données bidirectionnelle. Avec ce schéma de travail, si quelque chose de nouveau apparaît dans le champ de saisie, cela entraîne une modification des données. Et, en conséquence, lorsque les données changent, l'état du contrôle qui utilise ces données est mis à jour.
Ajoutons une directive au champ d'entrée
v-model
et lions ce champ à une propriété à name
partir des données du composant.
<input v-model="name">
Ajoutons maintenant le code de formulaire complet au modèle de composant:
<form class="review-form" @submit.prevent="onSubmit">
<p>
<label for="name">Name:</label>
<input id="name" v-model="name" placeholder="name">
</p>
<p>
<label for="review">Review:</label>
<textarea id="review" v-model="review"></textarea>
</p>
<p>
<label for="rating">Rating:</label>
<select id="rating" v-model.number="rating">
<option>5</option>
<option>4</option>
<option>3</option>
<option>2</option>
<option>1</option>
</select>
</p>
<p>
<input type="submit" value="Submit">
</p>
</form>
Comme vous pouvez le voir, les
v-model
champs input
, textarea
et sont équipés de la directive select
. Veuillez noter que lors de la configuration du champ select
, un modificateur a été utilisé .number
(nous en parlerons plus en détail ci-dessous). Cela vous permet de convertir les données correspondantes en un type Number
, alors qu'elles sont généralement représentées dans une chaîne.
Complétons l'ensemble de données du composant en y ajoutant les données auxquelles les contrôles décrits ci-dessus sont liés:
data() {
return {
name: null,
review: null,
rating: null
}
}
En haut du modèle de formulaire, vous pouvez voir que lorsque le formulaire est soumis, une méthode est appelée
onSubmit
. Nous créerons bientôt cette méthode. Mais d'abord, parlons du rôle de la construction .prevent
.
Ceci est un modificateur d'événement. Il empêche la page d'être rechargée après le déclenchement de l'événement
submit
. Il existe également d'autres modificateurs d'événements utiles . Certes, nous n'en parlerons pas.
Nous sommes maintenant prêts à créer une méthode
onSubmit
. Commençons par ce code:
onSubmit() {
let productReview = {
name: this.name,
review: this.review,
rating: this.rating
}
this.name = null
this.review = null
this.rating = null
}
Comme vous pouvez le voir, cette méthode crée un objet basé sur les données saisies par l'utilisateur. Une référence à celle-ci est écrite dans une variable
productReview
. Nous laissons tomber ici dans la null
valeur des propriétés name
, review
, rating
. Mais le travail n'est pas encore terminé. Nous devons encore envoyer quelque part productReview
. Où envoyer cet objet?
Il est judicieux de stocker les avis sur les produits au même endroit où les données des composants sont stockées
product
. Étant donné que le composant est product-review
imbriqué dans un composant product
, on peut dire qu'il product-review
s'agit d'un enfant du composant product
. Comme nous l'avons appris dans la leçon précédente, pour envoyer des données des composants enfants aux composants parents, vous pouvez utiliser les événements générés par $emit
.
Affinons la méthode
onSubmit
:
onSubmit() {
let productReview = {
name: this.name,
review: this.review,
rating: this.rating
}
this.$emit('review-submitted', productReview)
this.name = null
this.review = null
this.rating = null
}
Maintenant, nous générons un événement avec un nom
review-submitted
et y passons l'objet nouvellement créé productReview
.
Ensuite, nous devons organiser l'écoute de cet événement en plaçant les éléments
product
suivants dans le modèle :
<product-review @review-submitted="addReview"></product-review>
Cette ligne se lit comme suit: "Lorsqu'un événement se produit
review-submitted
, la méthode du addReview
composant doit être exécutée product
."
Voici le code de cette méthode:
addReview(productReview) {
this.reviews.push(productReview)
}
Cette méthode prend l'objet
productReview
qui provient de la méthode onSubmit
, puis le place dans un tableau reviews
stocké dans les données du composant product
. Mais il n'y a pas encore de tableau de ce type dans les données de ce composant. Alors ajoutons-le ici:
reviews: []
Merveilleux! Les éléments du formulaire sont maintenant liés aux données du composant
product-review
. Ces données sont utilisées pour créer l'objet productReview
. Et cet objet est passé, lors de la soumission du formulaire, au composant product
. En conséquence, l'objet est productReview
ajouté au tableau reviews
, qui est stocké dans les données du composant product
.
Affichage des avis sur les produits
Il ne reste plus qu'à afficher sur la page produit les avis laissés par les visiteurs du site. Nous allons faire cela dans le composant
product
en plaçant le code correspondant au-dessus du code avec lequel le composant product-review
est placé dans le composant product
.
<div>
<h2>Reviews</h2>
<p v-if="!reviews.length">There are no reviews yet.</p>
<ul>
<li v-for="review in reviews">
<p>{{ review.name }}</p>
<p>Rating: {{ review.rating }}</p>
<p>{{ review.review }}</p>
</li>
</ul>
</div>
Ici, nous créons une liste de critiques à l'aide de la directive
v-for
et affichons les données stockées dans l'objet en review
utilisant la notation par points.
Dans la balise,
<p>
nous vérifions s'il y a quelque chose dans le tableau reviews
(en vérifiant sa longueur). S'il n'y a rien dans le tableau, nous imprimons un message There are no reviews yet
.
Page du formulaire de commentaires
Validation du formulaire
Les formulaires contiennent souvent des champs qui doivent être remplis avant de soumettre le formulaire. Par exemple, nous ne voulons pas que les utilisateurs soumettent des avis dans lesquels le champ de texte de l'avis est vide.
Heureusement pour nous, HTML5 prend en charge le
required
. Son utilisation ressemble à ceci:
<input required >
Une telle construction entraînera l'affichage automatique d'un message d'erreur si l'utilisateur tente de soumettre un formulaire dans lequel le champ requis est vide.
Message d'erreur
Avoir des validateurs de champ de formulaire standard dans le navigateur est très agréable, car cela peut nous libérer de la création de nos propres validateurs de champ. Mais la manière dont la vérification standard des données est effectuée peut, dans certains cas particuliers, ne pas nous convenir. Dans cette situation, il est judicieux d'écrire votre propre code de validation de formulaire.
Validation de formulaire personnalisé
Parlons de la façon de créer votre propre système de validation de formulaire.
Incluons un
product-review
tableau pour stocker les messages d'erreur dans les données du composant . Appelons ça errors
:
data() {
return {
name: null,
review: null,
rating: null,
errors: []
}
}
Nous aimerions ajouter à ce tableau des informations sur les erreurs qui se produisent dans les situations où les champs de formulaire sont vides. Nous parlons du code suivant:
if(!this.name) this.errors.push("Name required.")
if(!this.review) this.errors.push("Review required.")
if(!this.rating) this.errors.push("Rating required.")
La première de ces lignes indique au système
name
de mettre errors
un message d'erreur dans le tableau si le champ est vide Name required
. Les autres chaînes qui valident les champs review
et fonctionnent de la même manière rating
. Si l'un d'entre eux est vide, array
un message d'erreur sera envoyé à la baie .
Où mettre ce code?
Puisque nous voulons que les messages d'erreur à écrire au tableau que lorsque, en essayant de soumettre le formulaire, il se trouve que les champs sont
name
, review
ou ne sont submit
pas remplies, nous pouvons placer ce code dans la méthode onSubmit
. De plus, nous réécrirons le code qui s'y trouve déjà, en y ajoutant quelques vérifications:
onSubmit() {
if(this.name && this.review && this.rating) {
let productReview = {
name: this.name,
review: this.review,
rating: this.rating
}
this.$emit('review-submitted', productReview)
this.name = null
this.review = null
this.rating = null
} else {
if(!this.name) this.errors.push("Name required.")
if(!this.review) this.errors.push("Review required.")
if(!this.rating) this.errors.push("Rating required.")
}
}
Maintenant, nous vérifions les champs
name
, review
et rating
. S'il y a des données dans tous ces champs, nous créons un objet basé sur eux productReview
et l'envoyons au composant parent. Ensuite, les propriétés correspondantes sont réinitialisées.
Si au moins l'un des champs s'avère vide, nous mettons
errors
un message d'erreur dans le tableau , en fonction de ce que l'utilisateur n'a pas entré avant de soumettre le formulaire.
Il ne reste plus qu'à afficher ces erreurs, ce qui peut être fait avec le code suivant:
<p v-if="errors.length">
<b>Please correct the following error(s):</b>
<ul>
<li v-for="error in errors">{{ error }}</li>
</ul>
</p>
Ici, une directive est utilisée
v-if
avec laquelle nous vérifions le tableau errors
pour la présence de messages d'erreur (en fait, nous analysons la longueur du tableau). S'il y a quelque chose dans le tableau, un élément est affiché <p>
, qui, lorsqu'il est appliqué v-for
, affiche une liste des erreurs du tableau errors
.
Messages d'erreur
Nous avons maintenant notre propre système de validation de formulaire.
Utilisation du modificateur .number
Le modificateur
.number
utilisé dans la directive v-model
peut être très utile. Mais lors de son application, gardez à l'esprit qu'il y a un problème qui lui est associé. Si la valeur correspondante est vide, elle sera représentée sous forme de chaîne et non de nombre. Le livre de recettes Vue offre une solution à ce problème. Il consiste à convertir explicitement la valeur correspondante en un type numérique:
Number(this.myNumber)
Atelier
Ajoutez la question suivante au formulaire: "Recommanderiez-vous ce produit?" Faites en sorte que l'utilisateur puisse y répondre en utilisant les boutons radio «oui» et «non». Vérifiez la réponse à cette question et incluez les données pertinentes dans l'objet
productReview
.
Résultat
Aujourd'hui, nous avons parlé de travailler avec des formulaires. Voici la chose la plus importante que vous ayez apprise aujourd'hui:
- Vous pouvez utiliser la directive pour organiser la liaison de données bidirectionnelle pour former des éléments
v-model
. - Le modificateur
.number
indique à Vue de convertir la valeur correspondante en un type numérique. Mais lorsque vous travaillez avec, il y a un problème lié au fait que les valeurs vides restent des chaînes. - Le modificateur d'événement
.prevent
vous permet d'empêcher le rechargement de la page après l'envoi du formulaire. - Avec Vue, vous pouvez implémenter un mécanisme assez simple pour la validation de formulaire personnalisé.
Avez-vous fait vos devoirs aujourd'hui?
→ Vue.js pour les débutants Leçon 1: Instance de Vue
→ Vue.js pour les débutants, Leçon 2: Liaison d'attributs
→ Vue.js pour les débutants, Leçon 3: Rendu conditionnel
→ Vue.js pour les débutants, Leçon 4: Listes de rendu
→ 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
→ Vue. js pour les débutants leçon 9: événements personnalisés