🧊

Svelteで生DOMを扱う

Reactでいうところの`ref`を、Svelteでどうやって扱うか。

まぁドキュメントにちゃんと書いてあるけども。

bind:this

https://svelte.dev/docs#bind_element

1つ目のやり方がこれ。

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

  let el = null;
  onMount(() => {
    const timer = setInterval(
      () => el.textContent = Date.now(),
      1000
    );

    return () => clearInterval(timer);
  });
</script>

<div bind:this={el} />

`bind:this`ディレクティブで、変数に入れる。

そしてその変数は、`onMount()`のフックで取る。
そうしないと、まだレンダリングされてないので、`undefined`になっちゃう。

use:action

https://svelte.dev/docs#use_action

2つ目のやりかた。

<script>
  import { myAction } from "./actions.js";
</script>

<div use:myAction />

というように、`use:関数名`って書く。

関数側はこのように。

export const myAction = (el) => {
  const timer = setInterval(
    () => el.textContent = Date.now(),
    1000
  );

  return {
    destroy() {
      clearInterval(timer);
    },
  };
};

`destory()`はこのDOM要素が破棄されるタイミングで呼ばれる。

こうすると、それ用の関数に処理を切り出せていい感じ。

パラメータを渡す

ちなみにDOM要素のほかにパラメータを受け取るためには、ディレクティブで渡せばよい。

<div use:myAction={2000} />
<div use:myAction2={{ foo, bar }} />

こうすると、第2引数で取れるようになる。

export const myAction = (el, duration = 1000) => {
  const timer = setInterval(
    () => el.textContent = Date.now(),
    duration
  );

  return {
    destroy() {
      clearInterval(timer);
    },
  };
};

渡したパラメータが更新されたら

リアクティブな値を渡した場合など。

export const myAction2 = (el, params) => {
  return {
    update(params) {
      // Do something
    },
    destroy() {},
  };
};

`update()`を用意しておくと、値が変わったときに呼ばれるようになる。