Cours Svelte et SvelteKit · Module 10: Actions
Mjolnir - Actions
Dans cette leçon4
Bienvenue dans la forge de Mjolnir ! Le marteau de Thor possède des pouvoirs extraordinaires. Les Actions dans Svelte sont comme ces pouvoirs - elles étendent les capacités des éléments du DOM.
Que sont les Actions ?
Les Actions sont des fonctions appelées lorsqu'un élément est monté dans le DOM. En Svelte 5, tu places la configuration et le nettoyage dans un $effect à l'intérieur de l'action : la fonction renvoyée par $effect s'exécute quand l'élément disparaît :
<script>
function myAction(node) {
// node est l'élément du DOM, déjà présent dans le document
console.log('Élément monté :', node);
$effect(() => {
// ici la configuration : écouteurs, bibliothèques
return () => {
// et ici le nettoyage, quand l'élément disparaît
console.log('Élément démonté');
};
});
}
</script>
<div use:myAction>
Élément avec une action
</div>Les actions ne s'exécutent pas pendant le rendu côté serveur (SSR) : elles ne démarrent que dans le navigateur.
L'API classique : un objet avec destroy
Avant l'arrivée de $effect, une action renvoyait un objet avec une méthode destroy() (et update(), vue dans la leçon suivante). Cette API fonctionne toujours et reste pratique dans les fichiers .js ordinaires : les runes comme $effect ne sont disponibles que dans les fichiers .svelte et .svelte.js.
// actions.js - un fichier JS ordinaire, sans runes
export function myAction(node) {
console.log('Élément monté :', node);
return {
destroy() {
console.log('Élément démonté');
}
};
}Exemple : Clic à l'extérieur
// actions.js
export function clickOutside(node, callback) {
function handleClick(event) {
if (!node.contains(event.target)) {
callback();
}
}
document.addEventListener('click', handleClick, true);
return {
destroy() {
document.removeEventListener('click', handleClick, true);
}
};
}<script>
import { clickOutside } from './actions.js';
let isOpen = $state(false);
</script>
{#if isOpen}
<div use:clickOutside={() => isOpen = false} class="dropdown">
Clique en dehors de moi pour fermer
</div>
{/if}Actions avec paramètres
<script>
function tooltip(node, text) {
let tooltipEl;
function show() {
tooltipEl = document.createElement('div');
tooltipEl.className = 'tooltip';
tooltipEl.textContent = text;
document.body.appendChild(tooltipEl);
const rect = node.getBoundingClientRect();
tooltipEl.style.left = rect.left + 'px';
tooltipEl.style.top = rect.bottom + 5 + 'px';
}
function hide() {
tooltipEl?.remove();
}
$effect(() => {
node.addEventListener('mouseenter', show);
node.addEventListener('mouseleave', hide);
return () => {
hide();
node.removeEventListener('mouseenter', show);
node.removeEventListener('mouseleave', hide);
};
});
}
</script>
<button use:tooltip={'Voici un bouton'}>
Survole-moi
</button>Mjolnir donne du pouvoir - les Actions donnent du pouvoir aux éléments !
Code de cette leçon : App.svelte
<script>
// Mjölnir - Pouvoirs assignés aux éléments
// use:action - comportements DOM supplémentaires
// Action simple - focus au montage
function autofocus(node) {
node.focus();
// Nettoyage en Svelte 5 : la fonction renvoyée par $effect
$effect(() => {
return () => console.log('Élément supprimé');
});
}
// Action avec paramètres
function tooltip(node, text) {
let tooltipEl;
function show() {
tooltipEl = document.createElement('div');
tooltipEl.textContent = text;
tooltipEl.className = 'tooltip';
document.body.appendChild(tooltipEl);
const rect = node.getBoundingClientRect();
tooltipEl.style.left = rect.left + rect.width / 2 + 'px';
tooltipEl.style.top = rect.top - 10 + 'px';
}
function hide() {
if (tooltipEl) {
tooltipEl.remove();
tooltipEl = null;
}
}
node.addEventListener('mouseenter', show);
node.addEventListener('mouseleave', hide);
// API classique des actions (toujours valable) : update et destroy
return {
// update - quand le paramètre change
update(newText) {
text = newText;
},
// nettoyage
destroy() {
hide();
node.removeEventListener('mouseenter', show);
node.removeEventListener('mouseleave', hide);
}
};
}
let tooltipText = $state('Je suis une infobulle !');
</script>
<main class="mjolnir">
<h1>Mjölnir - Actions</h1>
<p class="subtitle">use: - ajoute des pouvoirs aux éléments</p>
<section>
<h2>use:autofocus</h2>
<input use:autofocus placeholder="Focus automatique au démarrage !" />
</section>
<section>
<h2>use:tooltip</h2>
<input
bind:value={tooltipText}
placeholder="Change le texte de l’infobulle"
/>
<button use:tooltip={tooltipText}>
Survole-moi !
</button>
</section>
</main>
<style>
.mjolnir {
font-family: 'Georgia', serif;
max-width: 500px;
margin: 0 auto;
padding: 2rem;
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
color: #e8e8f7;
min-height: 100vh;
}
h1 {
color: #7cb3f0;
text-align: center;
}
.subtitle {
text-align: center;
color: #6a8ab9;
}
section {
background: rgba(124, 179, 240, 0.1);
border: 1px solid #7cb3f0;
border-radius: 8px;
padding: 1rem;
margin: 1rem 0;
}
h2 {
color: #7cb3f0;
font-size: 1rem;
margin-top: 0;
}
input {
width: 100%;
padding: 0.75rem;
background: rgba(0,0,0,0.3);
border: 1px solid #3a5f8a;
border-radius: 4px;
color: #e8e8f7;
margin-bottom: 0.5rem;
}
input:focus {
border-color: #7cb3f0;
outline: none;
}
button {
padding: 0.75rem 1.5rem;
background: #3a5f8a;
color: #e8e8f7;
border: 1px solid #7cb3f0;
border-radius: 4px;
cursor: pointer;
}
:global(.tooltip) {
position: fixed;
background: #ffd700;
color: #1a1a2e;
padding: 0.5rem 1rem;
border-radius: 4px;
font-size: 0.9rem;
transform: translate(-50%, -100%);
z-index: 1000;
pointer-events: none;
}
</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. Comment utilise-t-on une action sur un élément du DOM ?
2. Que peut retourner une fonction action ?