Skip to content

在 Vue 中接入 ​

适用于Vue 3.5及以上。先按快速开始准备包依赖,将其中的basic.ts放在组件旁边。@skynote/editor不依赖Vue,本页只是宿主集成示例,不是另一个已发布的Vue组件包。

完整组件 ​

创建VueCanvasExample.vue,与basic.ts放在同一目录,然后在自己的页面中导入并使用该组件。

vue
<script setup lang="ts">
import { onBeforeUnmount, onMounted, ref, useTemplateRef } from 'vue';
import type { SkyNoteEditor } from '@skynote/editor';

const host = useTemplateRef<HTMLElement>('host');
const message = ref('正在加载画布…');
let editor: SkyNoteEditor<HTMLElement> | undefined;
let disposed = false;

onMounted(async () => {
  try {
    // 浏览器模块只在客户端加载;切换页面后到达的模块不再创建实例。
    const { mountExample } = await import('./basic');
    if (disposed) return;
    editor = mountExample(host.value!);
    message.value = '';
  } catch {
    if (!disposed) message.value = '画布加载失败,请刷新重试。';
  }
});
onBeforeUnmount(() => {
  disposed = true;
  editor?.destroy();
});
</script>
<template>
  <section class="vue-canvas-example" aria-label="Vue接入示例">
    <div ref="host" data-canvas-host class="vue-canvas-host" />
    <p v-if="message" role="status">{{ message }}</p>
  </section>
</template>
<style scoped>
.vue-canvas-example {
  position: relative;
  height: 420px;
  overflow: hidden;
  background: var(--sn-canvas);
}
.vue-canvas-host {
  position: absolute;
  inset: 0;
  outline: none;
}
p {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  color: var(--sn-text-muted);
}
</style>

下面运行同一份组件源码:

正在加载画布…

生命周期与异步取消 ​

onMounted之后才导入浏览器运行时并挂载。加载期间离开页面时,disposed阻止晚到模块创建编辑器;创建成功的实例在onBeforeUnmount销毁。SDK实例使用普通变量,不进入深度响应式代理。

如果需要供模板控制按钮状态,单独保存canUndo等简单状态;订阅历史、选区或文档事件时,同时保存并调用解绑函数。不要为了刷新工具栏而在每次拖动时导出整份文档。

SSR、尺寸和焦点 ​

  • import type可以在服务端参与类型检查;浏览器运行时通过客户端生命周期动态导入。
  • 容器需要明确高度,示例为420px。实际布局可改为填满父容器,但父容器本身也必须有确定尺寸。
  • 首次在隐藏标签页中挂载时,先等待容器可见,再创建或适配视口。
  • 工具栏点击不要抢走画布焦点;可用键盘Tab访问按钮,同时给图标按钮提供无障碍名称。

示例使用文档站颜色变量。嵌入自己的应用时,可定义--sn-canvas和--sn-text-muted,或替换为自己的宿主Token。这些变量控制组件外壳,不自动改变画布主题。

继续接入 ​

需要文档保存时阅读保存与恢复,需要业务节点时阅读自定义节点。

可组合的画布能力,从一个想法开始。