Appearance
3. Données calculées
Présentation
Il arrive souvent que nous ne souhaitions pas exploiter telles quelles les données que nous récupérons d’une API. Nous pouvons avoir envie de les filtrer selon certains critères, ou encore les ranger dans un ordre précis.
Pour cela il est possible de modifier les données dès leur réception dans la méthode chargée de les récupérer. Mais comment faire si cette réorganisation varie en fonction des choix de l’utilisateur ? Nous devons à chaque fois récupérer les données de l’API à nouveau ?
Dans ce chapitre, nous allons voir comment calculer dynamiquement une donnée à partir d’autres données grâce aux données calculées. Cela nous permettra de concrétiser le filtrage et l’ordonnancement de nos chiens en fonction des choix de notre utilisateur.
Données calculées
Manipulation de primitives
La configuration de nos composants nous permettent de définir des données dynamiquement calculées en fonction d’autres données. Pour cela, il suffit de déclarer ses attributs dans le champ computed et d’y associer la fonction chargée d’effectuer le calcul :
jsx
<template>
<div>
<p>{{ number1 }} + {{ number2 }} = {{ sum }}</p>
</div>
</template>
<script>
export default {
name: 'MyComponent',
computed: {
sum: function() {
return this.number1 + this.number2
}
},
data() {
return {
number1: 4,
number2: 3
}
}
}
</script>Dans cette exemple, notre donnée calculée sum vaudra la somme de nos deux données number1 et number2. Ce qui est particulièrement intéressant, c’est que si l’une de nos données number1 ou number2 change de valeur, la donnée sum sera automatiquement recalculée en fonction des nouvelles valeurs.
Manipulation de tableaux
Les données calculées sont particulièrement utiles pour réorganiser des ensembles de données comme des tableaux d’objets. Elle nous permettent d’appliquer des méthodes telles que filter, sort, map et reverse sur nos tableaux.
TIP
💡 Si vous n’êtes pas familier avec les méthodes de réorganisation de tableau en Javascript, je vous invite à consulter la documentation MDN à leur sujet.
Reprenons notre tableau contenant les informations sur nos chiens. Nous allons définir une donnée calculée à partir de notre tableau :
jsx
<script>
export default {
name: 'DogsGallery',
computed: {
dogsOrganizedData: function() {
return this.dogsData
}
},
data() {
return {
dogsData: [],
search: "",
dogsSortType: "AZName"
}
},
...
}
</script>Pour le moment notre donnée calculée retourne exactement la même chose que notre donnée dogsData . Nous allons utiliser les méthodes sort et reverse pour ranger nos chiens en fonction des choix de l’utilisateur :
jsx
<script>
export default {
name: 'DogsGallery',
computed: {
dogsOrganizedData: function() {
const field = ["AZName", "ZAName"].includes(this.dogsSortType) ? "name" : "breed"
const reversed = ["ZAName", "ZABreed"].includes(this.dogsSortType)
const comparator = (a, b) => a[field].localeCompare(b[field])
let data = this.dogsData.sort(comparator)
if (reversed) data = data.reverse()
return data
}
},
data() {
return {
dogsData: [],
search: "",
dogsSortType: "AZName"
}
},
...
}
</script>Notre fonction détermine d’abord le champ concerné par le tri, et si le tri doit être renversé, c’est à dire dans l’ordre alphabétique inversé. Nous utilisons pour cela la méthode JS includes qui nous permet de vérifier qu’une valeur, ici dogsSortType, fait bien partie ou non d’un tableau de données.
Nous définissons ensuite une fonction qui va nous permettre de comparer deux à deux les champs des objets de notre tableau, et retourner -1 ou 1 en fonction du premier dans l’ordre alphabétique grâce à la méthode localeCompare.
Enfin, nous trions nos données grâce à cette fonction et inversons le résultat si nécessaire.
REMARQUE
👉 Notez que nous partons du principe ici que tous les noms des chiens et les races des chiens que nous envoie notre API sont des chaînes de caractères commençant par une majuscule, suivie de minuscules. Si vous n’êtes pas sûr du format dans lequel seront vos données, vous pouvez toutes les passer en minuscules au moment du tri avec la méthode toLowerCase() .
Il ne nous reste plus qu’à filtrer nos données en vérifiant qu’elles contiennent bien la chaîne de caractères présente dans notre donnée search. Pour cela, nous pouvons à nouveau utiliser includes, cette fois sur notre donnée search:
jsx
<script>
export default {
name: 'DogsGallery',
computed: {
dogsOrganizedData: function() {
const field = ["AZName", "ZAName"].includes(this.dogsSortType) ? "name" : "breed"
const reversed = ["ZAName", "ZABreed"].includes(this.dogsSortType)
const filterFunc = (a) => a.name.toLowerCase().includes(this.search.toLowerCase())
const comparator = (a, b) => a[field].localeCompare(b[field])
let data = this.dogsData.filter(filterFunc)
data = data.sort(comparator)
if (reversed) data = data.reverse()
return data
}
},
data() {
return {
dogsData: [],
search: "",
dogsSortType: "AZName"
}
},
...
}
</script>Pour que notre recherche de nom de soit pas sensible à la casse, nous repassons ici le contenu de la recherche et les noms des chiens en minuscule avant de les comparer grâce à la méthode .toLowerCase().
TIP
💡 Pour de meilleures performances, il est toujours préférable de d’abord filtrer des données avant de les ranger.
Si vous êtes suffisamment à l’aise avec la syntaxe Javascript, vous pouvez bien sûr raccourcir l’écriture et optimiser un peu cette fonction. Veillez toutefois à préserver une syntaxe avec des lignes courtes et explicites :
jsx
dogsOrganizedData: function() {
const field = ["AZName", "ZAName"].includes(this.dogsSortType) ? "name" : "breed"
const reversed = ["ZAName", "ZABreed"].includes(this.dogsSortType) ? -1 : 1
return this.dogsData
.filter((a) => a.name.toLowerCase().includes(this.search.toLowerCase()))
.sort((a, b) => a[field].localeCompare(b[field]) * reversed)
}
