Cours Vue.js · Module 11: Pinia

Les Getters dans Pinia

2 min de lecture
Dans cette leçon4

Les getters sont des valeurs calculées à partir du state - comme les panneaux d'analyse du NOVA LAB qui traitent les données brutes des capteurs et les présentent sous une forme lisible. Ils se mettent à jour automatiquement quand le state change.

Getters de base

En Composition API, les getters ne sont rien d'autre que des computed() :

1import { defineStore } from 'pinia'
2import { ref, computed } from 'vue'
3
4export const useInventoryStore = defineStore('inventory', () => {
5  const items = ref([
6    { name: 'Oxygen Tank', quantity: 12, category: 'life-support' },
7    { name: 'Water Filter', quantity: 5, category: 'life-support' },
8    { name: 'Solar Panel', quantity: 8, category: 'energy' },
9    { name: 'Drill Bit', quantity: 20, category: 'mining' }
10  ])
11
12  // Getter simple
13  const totalItems = computed(() =>
14    items.value.reduce((sum, item) => sum + item.quantity, 0)
15  )
16
17  // Getter de filtrage
18  const lifeSupportItems = computed(() =>
19    items.value.filter(item => item.category === 'life-support')
20  )
21
22  // Getter de vérification de condition
23  const hasShortage = computed(() =>
24    items.value.some(item => item.quantity < 3)
25  )
26
27  return { items, totalItems, lifeSupportItems, hasShortage }
28})

Getters utilisant d'autres getters

Les getters peuvent s'appuyer sur d'autres getters :

1const lowStockItems = computed(() =>
2  items.value.filter(item => item.quantity < 5)
3)
4
5const lowStockCount = computed(() => lowStockItems.value.length)
6
7const stockStatus = computed(() => {
8  if (lowStockCount.value === 0) return 'OK'
9  if (lowStockCount.value <= 2) return 'WARNING'
10  return 'CRITICAL'
11})

Getters avec paramètres

Un computed n'accepte pas d'arguments, mais tu peux retourner une fonction :

1// Getter avec paramètre - retourne une fonction
2const getItemsByCategory = computed(() => {
3  return (category) =>
4    items.value.filter(item => item.category === category)
5})
6
7const findItem = computed(() => {
8  return (name) =>
9    items.value.find(item =>
10      item.name.toLowerCase().includes(name.toLowerCase())
11    )
12})

Utilisation dans un composant :

1<template>
2  <div>
3    <p>Total: {{ store.totalItems }}</p>
4    <p>Status: {{ store.stockStatus }}</p>
5
6    <!-- Getter avec paramètre -->
7    <div v-for="item in store.getItemsByCategory('energy')" :key="item.name">
8      {{ item.name }}: {{ item.quantity }}
9    </div>
10  </div>
11</template>

Les getters dans storeToRefs

Les getters (computed) font partie de storeToRefs :

1<script setup>
2import { storeToRefs } from 'pinia'
3import { useInventoryStore } from '@/stores/inventory'
4
5const store = useInventoryStore()
6const { items, totalItems, hasShortage } = storeToRefs(store)
7</script>
Code de cette leçon : App.vue
1<script setup>
2import { ref, computed } from 'vue'
3
4// Simulation d'un Inventory Store avec getters
5const items = ref([
6  { name: 'Oxygen Tank', quantity: 12, category: 'life-support', unit: 'units' },
7  { name: 'Water Filter', quantity: 2, category: 'life-support', unit: 'units' },
8  { name: 'Solar Panel', quantity: 8, category: 'energy', unit: 'units' },
9  { name: 'Battery Pack', quantity: 15, category: 'energy', unit: 'units' },
10  { name: 'Drill Bit', quantity: 20, category: 'mining', unit: 'pcs' },
11  { name: 'Rock Sample Container', quantity: 1, category: 'mining', unit: 'units' }
12])
13
14const searchQuery = ref('')
15const selectedCategory = ref('all')
16
17// Getters
18const totalItems = computed(() =>
19  items.value.reduce((sum, item) => sum + item.quantity, 0)
20)
21
22const categories = computed(() =>
23  ['all', ...new Set(items.value.map(i => i.category))]
24)
25
26const filteredItems = computed(() => {
27  let result = items.value
28  if (selectedCategory.value !== 'all') {
29    result = result.filter(i => i.category === selectedCategory.value)
30  }
31  if (searchQuery.value) {
32    const q = searchQuery.value.toLowerCase()
33    result = result.filter(i => i.name.toLowerCase().includes(q))
34  }
35  return result
36})
37
38const lowStockItems = computed(() =>
39  items.value.filter(item => item.quantity < 5)
40)
41
42const stockStatus = computed(() => {
43  if (lowStockItems.value.length === 0) return 'OK'
44  if (lowStockItems.value.length <= 2) return 'WARNING'
45  return 'CRITICAL'
46})
47
48// Getter avec paramètre
49const getByCategory = computed(() => {
50  return (cat) => items.value.filter(i => i.category === cat)
51})
52</script>
53
54<template>
55  <div class="nova-lab">
56    <h1>NOVA LAB - Inventory Getters</h1>
57
58    <div class="stats-bar">
59      <div class="stat-card">
60        <div class="stat-value">{{ totalItems }}</div>
61        <div class="stat-label">Total Items</div>
62      </div>
63      <div class="stat-card">
64        <div class="stat-value" :class="stockStatus.toLowerCase()">{{ stockStatus }}</div>
65        <div class="stat-label">Stock Status</div>
66      </div>
67      <div class="stat-card">
68        <div class="stat-value warning">{{ lowStockItems.length }}</div>
69        <div class="stat-label">Low Stock</div>
70      </div>
71    </div>
72
73    <div class="controls">
74      <input v-model="searchQuery" placeholder="Search..." class="search-input" />
75      <select v-model="selectedCategory" class="select">
76        <option v-for="cat in categories" :key="cat" :value="cat">
77          {{ cat === 'all' ? 'All Categories' : cat }}
78        </option>
79      </select>
80    </div>
81
82    <div class="inventory-grid">
83      <div v-for="item in filteredItems" :key="item.name"
84        class="item-card" :class="{ 'low-stock': item.quantity < 5 }">
85        <div class="item-name">{{ item.name }}</div>
86        <div class="item-qty">{{ item.quantity }} {{ item.unit }}</div>
87        <div class="item-cat">{{ item.category }}</div>
88      </div>
89    </div>
90
91    <div v-if="lowStockItems.length" class="alert-box">
92      Low stock: {{ lowStockItems.map(i => i.name).join(', ') }}
93    </div>
94  </div>
95</template>
96
97<style scoped>
98.nova-lab {
99  background: #0a0e27;
100  color: #00ff88;
101  min-height: 100vh;
102  padding: 20px;
103  font-family: monospace;
104}
105h1 { color: #00ff88; margin-bottom: 20px; text-align: center; }
106.stats-bar { display: flex; gap: 10px; margin-bottom: 15px; justify-content: center; }
107.stat-card {
108  background: rgba(0, 180, 216, 0.1);
109  border: 2px solid #00b4d8;
110  padding: 12px 20px;
111  text-align: center;
112}
113.stat-value { font-size: 1.4em; font-weight: bold; }
114.stat-label { color: #00b4d8; font-size: 0.8em; margin-top: 4px; }
115.ok { color: #00ff88; }
116.warning { color: #ff9900; }
117.critical { color: #ff4444; }
118.controls { display: flex; gap: 10px; margin-bottom: 15px; max-width: 500px; margin: 0 auto 15px; }
119.search-input, .select {
120  background: #0a0e27;
121  border: 2px solid #00b4d8;
122  color: #00ff88;
123  padding: 8px;
124  font-family: monospace;
125  flex: 1;
126}
127.inventory-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 10px; }
128.item-card {
129  background: rgba(0, 255, 136, 0.05);
130  border: 2px solid #00ff88;
131  padding: 12px;
132}
133.item-card.low-stock { border-color: #ff4444; background: rgba(255, 68, 68, 0.1); }
134.item-name { font-weight: bold; margin-bottom: 5px; }
135.item-qty { color: #00b4d8; }
136.item-cat { color: #666; font-size: 0.85em; margin-top: 4px; }
137.alert-box {
138  margin-top: 15px;
139  padding: 10px;
140  background: rgba(255, 68, 68, 0.1);
141  border: 2px solid #ff4444;
142  color: #ff4444;
143}
144</style>

Tu as repéré une erreur dans cette leçon ?

Teste tes connaissances

Réponds aux questions de cette leçon. Choisis une réponse pour voir tout de suite si elle est correcte.

  1. 1. Que sont les getters dans Pinia ?

  2. 2. Comment définit-on les getters dans un store en Composition API ?

Voici 2 des 3 questions de cette leçon. Réponds aux autres dans le jeu.

Tâches pratiques dans le jeu

  • Éditeur de code

    Crée des getters dans un store Pinia

  • Tri horizontal

    Ordonne les éléments pour définir un getter dans un store Pinia

  • Clique dans l'ordre

    Ordonne les éléments pour créer un getter avec un paramètre

  • Éditeur de code

    Crée des getters qui filtrent les données selon des paramètres