Cours Svelte et SvelteKit · Module 3: Réactivité et Runes
$derived - Valeurs dérivées
Dans cette leçon5
$derived crée une valeur qui se met à jour automatiquement quand ses dépendances changent. C'est comme une rune qui réagit à d'autres runes !
Utilisation de base
<script>
let warriors = $state(10);
let ships = $state(2);
// Se met à jour automatiquement
let totalPower = $derived(warriors * 10 + ships * 50);
let armyStatus = $derived(
totalPower > 200 ? 'Mighty army!' : 'Need more warriors'
);
</script>
<p>Warriors: {warriors}, Ships: {ships}</p>
<p>Power: {totalPower}</p>
<p>Status: {armyStatus}</p>$derived vs $state
<script>
let a = $state(5);
let b = $state(3);
// Ne fais PAS ça - synchronisation manuelle
let sumWrong = $state(a + b);
// sumWrong ne se mettra pas à jour quand a ou b changent !
// Utilise $derived
let sumRight = $derived(a + b);
// sumRight sera toujours à jour !
</script>Calculs complexes
<script>
let items = $state([
{ name: 'Sword', value: 100, count: 2 },
{ name: 'Shield', value: 50, count: 5 },
{ name: 'Helmet', value: 75, count: 3 }
]);
// Calculs sur le tableau
let totalItems = $derived(
items.reduce((sum, item) => sum + item.count, 0)
);
let totalValue = $derived(
items.reduce((sum, item) => sum + item.value * item.count, 0)
);
let mostValuable = $derived(
items.reduce((max, item) =>
item.value > max.value ? item : max
)
);
</script>
<p>Items: {totalItems}</p>
<p>Value: {totalValue} gold</p>
<p>Most valuable: {mostValuable.name}</p>$derived.by - Logique complexe
Pour des calculs plus complexes, utilise $derived.by :
<script>
let warriors = $state([
{ name: 'Ragnar', strength: 95, isAlive: true },
{ name: 'Bjorn', strength: 88, isAlive: true },
{ name: 'Ivar', strength: 70, isAlive: false }
]);
// Logique complexe en plusieurs étapes
let battleReport = $derived.by(() => {
const alive = warriors.filter(w => w.isAlive);
const totalStrength = alive.reduce((sum, w) => sum + w.strength, 0);
const avgStrength = alive.length > 0
? totalStrength / alive.length
: 0;
return {
aliveCount: alive.length,
totalStrength,
avgStrength: Math.round(avgStrength),
strongest: alive.sort((a, b) => b.strength - a.strength)[0]?.name ?? 'None'
};
});
</script>
<div class="report">
<h3>Battle Report</h3>
<p>Alive: {battleReport.aliveCount}</p>
<p>Total strength: {battleReport.totalStrength}</p>
<p>Average strength: {battleReport.avgStrength}</p>
<p>Strongest: {battleReport.strongest}</p>
</div>Chaîne de valeurs dérivées
<script>
let baseValue = $state(10);
// Chaque valeur dérivée dépend de la précédente
let doubled = $derived(baseValue * 2); // 20
let withBonus = $derived(doubled + 5); // 25
let final = $derived(withBonus * 1.1); // 27.5
</script>Les valeurs dérivées forment une chaîne de magie runique !
Code de cette leçon : App.svelte
<script>
// $derived - derived values
let items = $state([
{ name: 'Sword', value: 100, count: 2 },
{ name: 'Shield', value: 50, count: 5 },
{ name: 'Helmet', value: 75, count: 3 }
]);
// Simple derived
let totalItems = $derived(
items.reduce((sum, i) => sum + i.count, 0)
);
let totalValue = $derived(
items.reduce((sum, i) => sum + i.value * i.count, 0)
);
// $derived.by for complex logic
let report = $derived.by(() => {
const total = items.reduce((sum, i) => sum + i.count, 0);
const value = items.reduce((sum, i) => sum + i.value * i.count, 0);
const mostValuable = items.reduce((max, i) =>
i.value > max.value ? i : max
);
return {
total,
value,
average: total > 0 ? Math.round(value / total) : 0,
mostValuable: mostValuable.name
};
});
function addItem() {
items.push({ name: 'Axe', value: 80, count: 1 });
}
</script>
<main class="treasury">
<h1>Treasury</h1>
<section>
<h2>Items</h2>
<table>
<thead>
<tr>
<th>Item</th>
<th>Value</th>
<th>Quantity</th>
<th>Total</th>
</tr>
</thead>
<tbody>
{#each items as item}
<tr>
<td>{item.name}</td>
<td>{item.value}</td>
<td>{item.count}</td>
<td>{item.value * item.count}</td>
</tr>
{/each}
</tbody>
</table>
<button onclick={addItem}>+ Add Axe</button>
</section>
<section class="summary">
<h2>Summary ($derived)</h2>
<div class="stats">
<div class="stat">
<span class="label">Items</span>
<span class="value">{totalItems}</span>
</div>
<div class="stat">
<span class="label">Value</span>
<span class="value">{totalValue}</span>
</div>
</div>
</section>
<section class="report">
<h2>Report ($derived.by)</h2>
<p>Total: <strong>{report.total}</strong> items</p>
<p>Value: <strong>{report.value}</strong></p>
<p>Average: <strong>{report.average}</strong>/pc</p>
<p>Most valuable: <strong>{report.mostValuable}</strong></p>
</section>
</main>
<style>
.treasury {
font-family: 'Georgia', serif;
max-width: 600px;
margin: 0 auto;
padding: 2rem;
background: #1a0f0a;
color: #e8d5b7;
}
h1, h2 {
color: #d4af37;
}
section {
background: rgba(212, 175, 55, 0.1);
border: 1px solid #d4af37;
border-radius: 8px;
padding: 1rem;
margin-bottom: 1rem;
}
table {
width: 100%;
border-collapse: collapse;
margin-bottom: 1rem;
}
th, td {
padding: 0.5rem;
text-align: left;
border-bottom: 1px solid #3d2914;
}
th {
color: #d4af37;
}
button {
padding: 0.5rem 1rem;
background: #3d2914;
color: #e8d5b7;
border: 1px solid #d4af37;
border-radius: 4px;
cursor: pointer;
}
.stats {
display: flex;
gap: 2rem;
}
.stat {
text-align: center;
}
.stat .label {
display: block;
color: #8b7355;
font-size: 0.9rem;
}
.stat .value {
font-size: 1.5rem;
color: #d4af37;
}
strong {
color: #d4af37;
}
</style>Entrées de la documentation utilisées dans cette leçon
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. À quoi sert $derived ?
2. Quand utiliser $derived.by plutôt que $derived ?
Tâches pratiques dans le jeu
- Éditeur de code
Complète le code pour que doubled soit le double de la valeur de count