项目

Nuxt.js 集成 tiptap

引言

本指南将指导您如何在 Nuxt.js 项目中集成 Tiptap。

需求

  • 在您的机器上安装 Node.js
  • Vue 有基本了解

1. 创建项目(可选)

如果您已经有现有的 Vue 项目,也可以直接跳过这一步。直接进入下一步。

为了演示,我们从一个名为 my-tiptap-project 的新 Nuxt.js 项目开始。以下命令将设置所需的一切。它会问很多问题,您可以根据喜好选择或使用默认值。

# 创建项目
npm init nuxt-app my-tiptap-project

# 改变目录
cd my-tiptap-project

2. 安装依赖

好了,无聊的模板工作到此为止。现在让我们终于安装 Tiptap!下面的例子需要 @tiptap/vue-2 包及其一些组件,@tiptap/pm 包,以及 @tiptap/starter-kit,它包含了快速入门时最常见的扩展。

npm install @tiptap/vue-2 @tiptap/pm @tiptap/starter-kit

如果您按照步骤 1 和 2 进行操作,现在可以使用 npm run dev 启动项目,并在最喜欢的浏览器中打开 http://localhost:8080/。如果您在现有项目中工作,这可能会有所不同。

3. 创建新组件

要实际开始使用 Tiptap,您需要向应用添加一个新组件。我们将其命名为 TiptapEditor,并在 components/TiptapEditor.vue 中放入以下示例代码。

这是通过 Vue 快速启动 Tiptap 的最快方式。它将为您提供一个基础版本的 Tiptap,没有按钮。别担心,很快就能添加更多功能。

<template>
  <editor-content :editor="editor" />
</template>

<script>
  import { Editor, EditorContent } from "@tiptap/vue-2";
  import StarterKit from "@tiptap/starter-kit";

  export default {
    components: {
      EditorContent,
    },

    data() {
      return {
        editor: null,
      };
    },

    mounted() {
      this.editor = new Editor({
        content: "<p>我正在使用 Vue.js 运行 Tiptap。🎉</p>",
        extensions: [StarterKit],
      });
    },

    beforeDestroy() {
      this.editor.destroy();
    },
  };
</script>

4. 将其添加到应用

现在,让我们将 pages/index.vue 的内容替换为以下示例代码,以便在我们的应用中使用新的 TiptapEditor 组件。

<template>
  <div>
    <client-only>
      <tiptap-editor />
    </client-only>
  </div>
</template>
<script>
  import TiptapEditor from "~/components/TiptapEditor.vue";
  export default {
    components: {
      TiptapEditor,
    },
  };
</script>

请注意,Tiptap 必须在客户端运行,而不是在服务器端。编辑器需要包裹在 <client-only> 标签内。了解更多关于客户端只组件的信息。

现在您应该能在浏览器中看到 Tiptap。是时候给自己鼓掌了! :)

5. 使用 v-model(可选)

您可能习惯于在表单中使用 v-model 绑定数据,Tiptap 也支持。这是一个可以在您的项目中整合的可用组件示例:

https://embed.tiptap.dev/preview/GuideGettingStarted/VModel

<template>
  <editor-content :editor="editor" />
</template>

<script>
  import { Editor, EditorContent } from "@tiptap/vue-2";
  import StarterKit from "@tiptap/starter-kit";

  export default {
    components: {
      EditorContent,
    },

    props: {
      value: {
        type: String,
        default: "",
      },
    },

    data() {
      return {
        editor: null,
      };
    },

    watch: {
      value(value) {
        // HTML
        const isSame = this.editor.getHTML() === value;

        // JSON
        // const isSame = JSON.stringify(this.editor.getJSON()) === JSON.stringify(value)

        if (isSame) {
          return;
        }

        this.editor.commands.setContent(value, false);
      },
    },

    mounted() {
      this.editor = new Editor({
        content: this.value,
        extensions: [StarterKit],
        onUpdate: () => {
          // HTML
          this.$emit("input", this.editor.getHTML());

          // JSON
          // this.$emit('input', this.editor.getJSON())
        },
      });
    },

    beforeDestroy() {
      this.editor.destroy();
    },
  };
</script>
在本文档中