Cours Svelte et SvelteKit · Module 5: Liaisons

bind:this - Références DOM

2 min de lecture ·
Dans cette leçon5

bind:this donne accès à un élément du DOM, comme saisir le pont de Bifrost !

Utilisation de base

<script>
  let inputElement;

  function focusInput() {
    inputElement.focus();
  }
</script>

<input bind:this={inputElement} placeholder="Click the button..." />
<button onclick={focusInput}>Focus on input</button>

Canvas

<script>
  import { onMount } from 'svelte';

  let canvas;

  onMount(() => {
    const ctx = canvas.getContext('2d');

    // Dessine une rune
    ctx.fillStyle = 'gold';
    ctx.font = '48px serif';
    ctx.fillText('ᚱ', 50, 60);
  });
</script>

<canvas bind:this={canvas} width="200" height="100"></canvas>

Audio et vidéo

<script>
  let audio;
  let isPlaying = $state(false);
  let currentTime = $state(0);
  let duration = $state(0);

  function togglePlay() {
    if (isPlaying) {
      audio.pause();
    } else {
      audio.play();
    }
    isPlaying = !isPlaying;
  }
</script>

<audio
  bind:this={audio}
  bind:currentTime
  bind:duration
  src="/horn.mp3"
></audio>

<button onclick={togglePlay}>
  {isPlaying ? 'Pause' : 'Play'}
</button>

<p>Time: {Math.floor(currentTime)} / {Math.floor(duration)}</p>

bind:this avec des composants

<script>
  import WarriorPanel from './WarriorPanel.svelte';

  let panel;

  function openPanel() {
    panel.open(); // Appelle une méthode du composant
  }
</script>

<WarriorPanel bind:this={panel} />
<button onclick={openPanel}>Open panel</button>
<!-- WarriorPanel.svelte -->
<script>
  let isOpen = $state(false);

  export function open() {
    isOpen = true;
  }

  export function close() {
    isOpen = false;
  }
</script>

{#if isOpen}
  <div class="panel">
    Warrior panel
    <button onclick={close}>Close</button>
  </div>
{/if}

bind:value avec ton propre composant ($bindable)

bind: fonctionne aussi avec tes composants, mais seulement sur les props marquées avec $bindable() (tu les as découvertes à Asgard, dans le module 4). Le composant déclare une telle prop, et le parent la lie avec bind:value :

<!-- Slider.svelte -->
<script>
  let { value = $bindable(50), label = '' } = $props();
</script>

<label>
  {label}: {value}
  <input type="range" min="0" max="100" bind:value />
</label>
<!-- App.svelte -->
<script>
  import Slider from './Slider.svelte';

  let health = $state(100);
</script>

<Slider bind:value={health} label="Santé" />
<p>Santé du guerrier : {health}</p>

Déplacer le curseur modifie health dans le parent. Sans $bindable(), un tel bind:value se termine par une erreur : la prop circule alors seulement du parent vers l'enfant. Dans l'éditeur ci-dessous, Slider et TextInput fonctionnent de la même façon.

Code de cette leçon : App.svelte
<script>
  // Svelte 5: $bindable() - bindable props
  import Slider from './Slider.svelte';
  import TextInput from './TextInput.svelte';

  let health = $state(100);
  let strength = $state(75);
  let warriorName = $state('Ragnar');
</script>

<main class="stats-panel">
  <h1>Stats Panel</h1>
  <p class="subtitle">Svelte 5: $bindable() props</p>

  <section>
    <h2>Warrior name</h2>
    <TextInput bind:value={warriorName} label="Name" />
    <p>Hello, <strong>{warriorName}</strong>!</p>
  </section>

  <section>
    <h2>Stats</h2>

    <Slider
      bind:value={health}
      label="Health"
      color="#ff4444"
    />

    <Slider
      bind:value={strength}
      label="Strength"
      color="#ffd700"
    />
  </section>

  <div class="preview">
    <h2>{warriorName}</h2>
    <div class="stat">
      <span>{health}</span>
      <span>{strength}</span>
    </div>
    <p class="total">Total power: {health + strength}</p>
  </div>
</main>

<style>
  .stats-panel {
    font-family: 'Georgia', serif;
    max-width: 500px;
    margin: 0 auto;
    padding: 2rem;
    background: #1a0f0a;
    color: #e8d5b7;
    min-height: 100vh;
  }

  h1 {
    color: #d4af37;
    text-align: center;
  }

  .subtitle {
    text-align: center;
    color: #8b7355;
  }

  section {
    background: rgba(212, 175, 55, 0.1);
    border: 1px solid #d4af37;
    border-radius: 8px;
    padding: 1rem;
    margin: 1rem 0;
  }

  h2 {
    color: #d4af37;
    font-size: 1rem;
    margin-top: 0;
  }

  strong {
    color: #ffd700;
  }

  .preview {
    background: rgba(255, 215, 0, 0.1);
    border: 2px solid #ffd700;
    border-radius: 8px;
    padding: 1.5rem;
    text-align: center;
  }

  .preview h2 {
    color: #ffd700;
    font-size: 1.5rem;
    margin: 0;
  }

  .stat {
    display: flex;
    justify-content: center;
    gap: 2rem;
    margin: 1rem 0;
    font-size: 1.25rem;
  }

  .total {
    color: #b19cd9;
    font-size: 1rem;
  }
</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. 1. À quoi sert bind:this ?

Tâches pratiques dans le jeu

  • Éditeur de code

    Complète le code pour obtenir une référence vers le canvas : onMount y dessine ensuite une rune

Articles utiles