# Svelte

> Fabric.js Svelte 用法：在 onMount 里创建画布，把 createDocumentStateStore 变成 Svelte store。

Source: https://fabricjs-document-engine.jscrate.dev/zh/docs/frameworks/svelte
Last updated: 2026-09-28

Fabric.js Svelte 组件要在 `onMount` 里创建画布，因为那时 `<canvas>` 元素才存在。`createDocumentStateStore` 本身就有 `subscribe` 方法，所以把它变成 Svelte store 只要一行。

## 组件

```svelte
<script lang="ts">
  import { Canvas, Rect } from "fabric";
  import {
    createDocumentEngine,
    createDocumentStateStore,
    type DocumentEngine,
  } from "fabricjs-document-engine";
  import { onMount } from "svelte";
  import { readable, type Readable } from "svelte/store";

  let element: HTMLCanvasElement;
  let engine: DocumentEngine | undefined;
  let state: Readable<ReturnType<ReturnType<typeof createDocumentStateStore>["getSnapshot"]>> | undefined;

  onMount(() => {
    const canvas = new Canvas(element, { width: 800, height: 500 });
    engine = createDocumentEngine({ canvas });
    const store = createDocumentStateStore(engine);

    state = readable(store.getSnapshot(), (set) =>
      store.subscribe(() => set(store.getSnapshot()))
    );

    return () => {
      store.destroy();
      engine?.destroy();
      canvas.dispose();
    };
  });

  function addSquare() {
    engine?.canvas.add(new Rect({ width: 80, height: 60, fill: "#e9c46a" }));
  }
</script>

<div role="toolbar">
  <button on:click={addSquare}>Square</button>
  <button disabled={!$state?.canUndo} on:click={() => engine?.undo()}>
    Undo {$state?.undoLabel ?? ""}
  </button>
  <button disabled={!$state?.canRedo} on:click={() => engine?.redo()}>Redo</button>
</div>
<canvas bind:this={element} aria-label="Drawing canvas"></canvas>
```

## store 怎么工作

`readable(initial, start)` 会在第一个组件订阅时调用 `start`，在最后一个组件离开时调用它返回的函数。`store.subscribe` 返回的正好就是取消订阅的函数，所以 Svelte store 和引擎的 store 不用额外代码就能保持同步。

## SvelteKit

Fabric.js 需要浏览器。在 SvelteKit 里，`onMount` 只在浏览器中运行，所以上面的 Fabric.js Svelte 代码在服务端渲染时是安全的。如果你在共享模块顶部导入了 Fabric.js，请把这个导入移进组件里。

要保存，请给 `createDocumentEngine` 加上[存储适配器](https://fabricjs-document-engine.jscrate.dev/zh/docs/storage/storage-adapters)。[原生 JavaScript](https://fabricjs-document-engine.jscrate.dev/zh/docs/frameworks/vanilla-js) 指南展示了不用框架时同样的引擎调用。
