探索 Tiptap V3 的最新功能

Nuxt

本指南涵盖了如何将 Tiptap 集成到你的 Nuxt.js 项目中,附带代码示例。

系统要求

  • Node 已安装在你的机器上
  • Vue 使用经验

创建项目(可选)

如果你已经有一个 Nuxt.js 项目,那也没关系。可以跳过这一步。

为了这个项目的目的,从一个名为 my-tiptap-project 的新 Nuxt.js 项目开始。以下命令设置了我们需要的一切。它会问很多问题,但只需选择你喜欢的选项或使用默认设置即可。

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

# 更改目录
cd my-tiptap-project

安装依赖

够了,这些无聊的模板工作。让我们安装 Tiptap!对于以下示例,你需要 @tiptap/vue-3 包以及一些组件,@tiptap/pm 包和 @tiptap/starter-kit,后者包含了最常见的扩展,可以快速入门。

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

如果你按照步骤 1 和 2 使用,现在可以通过 npm run dev 启动项目,并在你喜欢的浏览器中打开 http://localhost:8080/。如果你在处理一个已有项目,可能会有所不同。

集成 Tiptap

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

这是让 Tiptap 与 Vue 一起快速启动的最简单方法。它将为你提供一个非常基本的 Tiptap 版本,没有任何按钮。别担心,你将很快能够添加更多功能。

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

<script>
  import { Editor, EditorContent } from '@tiptap/vue-3'
  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],
      })
    },

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

将其添加到你的应用中

现在,让我们用以下示例代码替换 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。给自己一个赞吧!:)

使用 v-model(可选)

你可能习惯于在表单中使用 v-model 绑定数据。这在 Tiptap 中也是可能的。以下是一个可以在你的项目中集成的工作示例组件:

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

<script>
  import { Editor, EditorContent } from '@tiptap/vue-3'
  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())
        },
      })
    },

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