Kurs Svelte i SvelteKit · Moduł 10: Akcje

Aktualizacja parametrów

2 min czytania ·
W tej lekcji3

update() - Reaguj na zmiany parametrów

Akcja jest wywoływana tylko raz. Gdy parametr się zmieni, Svelte nie wywoła jej ponownie - zamiast tego wywoła metodę update() ze zwróconego obiektu, przekazując nową wartość:

export function tooltip(node, text) {
  let tooltipEl;
  let currentText = text;

  // ... show/hide logic

  return {
    update(newText) {
      currentText = newText;
      if (tooltipEl) {
        tooltipEl.textContent = newText;
      }
    },
    destroy() {
      // cleanup
    }
  };
}
<script>
  import { tooltip } from './actions.js';

  let message = $state('Początkowy tekst');
</script>

<input bind:value={message} />
<button use:tooltip={message}>
  Hover me
</button>

Obiekt jako parametr

export function draggable(node, options = {}) {
  let { axis = 'both', bounds = null } = options;

  // ... logic

  return {
    update(newOptions) {
      axis = newOptions.axis ?? 'both';
      bounds = newOptions.bounds ?? null;
    },
    destroy() {
      // cleanup
    }
  };
}
<div use:draggable={{ axis: 'x', bounds: 'parent' }}>
  Drag me horizontally
</div>

Nowość: attachments ({@attach})

Od Svelte 5.29 zamiast akcji możesz użyć attachments. Attachment to funkcja, która dostaje element i może zwrócić funkcję sprzątającą. W przeciwieństwie do akcji jest w pełni reaktywny: gdy zmieni się stan użyty w jego wywołaniu, Svelte posprząta go i uruchomi ponownie, więc nie potrzebujesz update().

<script>
  let message = $state('Początkowy tekst');

  function tooltip(text) {
    return (node) => {
      node.title = text;
      return () => node.removeAttribute('title');
    };
  }
</script>

<input bind:value={message} />
<button {@attach tooltip(message)}>Najedź na mnie</button>

Akcje (use:) nadal są w pełni wspierane i znajdziesz je w wielu bibliotekach, dlatego w tej lokacji ćwiczymy właśnie je.

Kod do tej lekcji: App.svelte
<script>
  // Akcje z eventami - click outside, longpress
  import { clickOutside } from './actions.js';
  import { longpress } from './actions.js';

  let modalOpen = $state(false);
  let message = $state('');

  function handleClickOutside() {
    modalOpen = false;
  }

  function handleLongpress() {
    message = 'Long press wykryty!';
    setTimeout(() => message = '', 2000);
  }
</script>

<main class="actions-demo">
  <h1>Actions z eventami</h1>

  <section>
    <h2>use:clickOutside</h2>
    <button onclick={() => modalOpen = true}>Otwórz modal</button>

    {#if modalOpen}
      <div class="overlay">
        <div class="modal" use:clickOutside onoutclick={handleClickOutside}>
          <h3>Modal</h3>
          <p>Kliknij poza mną, by zamknąć</p>
        </div>
      </div>
    {/if}
  </section>

  <section>
    <h2>use:longpress</h2>
    <button
      use:longpress={500}
      onlongpress={handleLongpress}
    >
      Przytrzymaj 500ms
    </button>
    {#if message}
      <p class="message">{message}</p>
    {/if}
  </section>
</main>

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

  h1 {
    color: #7cb3f0;
    text-align: center;
  }

  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;
  }

  button {
    padding: 0.75rem 1.5rem;
    background: #3a5f8a;
    color: #e8e8f7;
    border: 1px solid #7cb3f0;
    border-radius: 4px;
    cursor: pointer;
  }

  .overlay {
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,0.7);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 100;
  }

  .modal {
    background: #16213e;
    border: 2px solid #7cb3f0;
    border-radius: 8px;
    padding: 2rem;
    min-width: 300px;
    text-align: center;
  }

  .modal h3 {
    color: #7cb3f0;
    margin-top: 0;
  }

  .message {
    margin-top: 0.5rem;
    padding: 0.5rem;
    background: rgba(255, 215, 0, 0.2);
    border-radius: 4px;
    color: #ffd700;
  }
</style>

Hasła z dokumentacji w tej lekcji

Widzisz błąd w tej lekcji?

Sprawdź się

Odpowiedz na pytania z tej lekcji. Wybierz odpowiedź, a od razu zobaczysz, czy jest poprawna.

  1. 1. Która metoda w obiekcie zwracanym z action reaguje na zmiany parametrów?

Przydatne artykuły