# 建立第一个编辑器

从一个 Vue 组件开始，理解创建、挂载和销毁。

这一章先做一件事：在 Vue 页面中放入能输入、选择和撤销的编辑器。先用浏览器原生 DOM 视图理解 Core 的用法，后面的章节再加入 Canvas、分页和产品界面。

你需要了解 Vue 的组件和生命周期，并准备 Node.js 与 pnpm。已有 Vue 3 项目可以直接从安装依赖开始。

## 1. 准备 Vue 项目

```sh [终端]
pnpm create vite my-editor --template vue-ts
cd my-editor
pnpm install
pnpm add @quirekit/core@alpha @quirekit/starter-kit@alpha @quirekit/dom-view@alpha @quirekit/pm-view@alpha
```

这几个包各负责一件事：`core` 管理文档和命令，`starter-kit` 提供段落、标题、粗体等常用能力，`dom-view` 把文档显示为可编辑的 DOM。`pm-view` 的基础样式保留正文空白和原生选区的显示方式。QuireKit 包应使用同一发布批次。

## 2. 创建编辑器组件

新建 `src/Editor.vue`。Vue 负责提供一个空元素；`Editor` 在组件挂载后接管这个元素中的编辑内容。

```vue [src/Editor.vue]
<script setup lang="ts">
import { onBeforeUnmount, onMounted, ref } from 'vue'
import { Editor } from '@quirekit/core'
import { StarterKit } from '@quirekit/starter-kit'
import { DomViewExtension } from '@quirekit/dom-view'
import '@quirekit/pm-view/style/prosemirror.css'

const element = ref<HTMLElement>()
let editor: Editor | undefined

onMounted(() => {
  editor = new Editor({
    element: element.value,
    mode: 'dom',
    extensions: [StarterKit, DomViewExtension],
    content: '<p>我的第一个 QuireKit 编辑器。</p>',
  })
})

onBeforeUnmount(() => editor?.destroy())
</script>

<template><div ref="element" /></template>
```

`element` 指定显示位置，`extensions` 决定可以编辑哪些内容，`content` 是初始正文。`mode: 'dom'` 选择刚安装的 DOM 视图。创建一次即可，文字输入时不需要重新创建 Editor。

`onMounted` 保证挂载元素已经存在；`destroy()` 释放编辑视图和监听器。因此这段组件也可以放在带 SSR 的应用中：服务端只渲染外层元素，编辑器在浏览器中创建。

## 3. 放到页面里

在 `src/App.vue` 中导入并使用组件，然后运行 `pnpm dev`。

```vue [src/App.vue]
<script setup lang="ts">
import Editor from './Editor.vue'
</script>

<template><Editor /></template>
```

你应该能点击正文输入，拖动选择文字，并通过系统快捷键撤销。下面运行的是同样的接入方式，可以直接试用；源码只有一个组件文件。

### tutorial/editor.vue

```vue
<script setup lang="ts">
import { onBeforeUnmount, onMounted, ref } from "vue";
import { Editor } from "@quirekit/core";
import { StarterKit } from "@quirekit/starter-kit";
import { DomViewExtension } from "@quirekit/dom-view";
import "@quirekit/pm-view/style/prosemirror.css";

const props = withDefaults(defineProps<{
  /** Language of the initial example text; changing it does not replace edits. */
  locale?: "zh-CN" | "en";
}>(), { locale: "zh-CN" });
const element = ref<HTMLElement>();
let editor: Editor | undefined;

onMounted(() => {
  editor = new Editor({
    element: element.value,
    mode: "dom",
    extensions: [StarterKit, DomViewExtension],
    content: props.locale === "en" ? "<p>My first QuireKit editor.</p>" : "<p>我的第一个 QuireKit 编辑器。</p>",
  });
});
onBeforeUnmount(() => editor?.destroy());
</script>

<template><div ref="element" class="p-qk-surface" /></template>

```

## 接下来增加什么

现在有了编辑器的骨架，但还没有工具栏和分页工作区。下一章先解释[文档模型](/build/model)：为什么正文要存成结构化数据，以及普通文章和 Word 文档为什么需要不同的扩展。随后[挂载 View](/build/view)会把 DOM 视图换成 Canvas/SVG。

如果你已经熟悉这些基础，可以直接查阅[完整工作区示例](/build/reference)。它包含文件操作和状态管理，每个文件的用途在该页单独说明。
