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

要求

  • 你的计算机上已安装 Node
  • 具备 Vue 使用经验

创建项目(可选)

如果你已经有一个 Nuxt.js 项目,那也没问题,可以跳过此步骤。

在本项目中,我们将从头开始创建一个新的 Nuxt.js 项目,命名为 my-tiptap-project。执行以下命令即可设置所需的一切。它会问你很多问题,你可以选择自己喜欢的选项或使用默认设置。

  1. # 创建项目
  2. npm init nuxt-app my-tiptap-project
  3. # 进入项目目录
  4. cd my-tiptap-project

安装依赖

好了,模板项目已经准备好,接下来让我们安装 Tiptap!在这个示例中,你需要安装 @tiptap/vue-3 包和一些组件、@tiptap/pm 包,以及 @tiptap/starter-kit,它包含了大多数常见的扩展,可以帮助你快速上手。

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

如果你完成了步骤 1 和 2,你可以通过运行 npm run dev 启动项目,并在浏览器中打开 http://localhost:8080/。如果你是在现有项目中操作,端口号可能会有所不同。

集成 Tiptap

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

这是在 Vue 中快速运行 Tiptap 的最快方法。它提供了一个非常基本的 Tiptap 版本,不带任何按钮。不用担心,稍后你可以添加更多功能。

  1. <template>
  2. <editor-content :editor="editor" />
  3. </template>
  4. <script>
  5. import { Editor, EditorContent } from '@tiptap/vue-3'
  6. import StarterKit from '@tiptap/starter-kit'
  7. export default {
  8. components: {
  9. EditorContent,
  10. },
  11. data() {
  12. return {
  13. editor: null,
  14. }
  15. },
  16. mounted() {
  17. this.editor = new Editor({
  18. content: '<p>I'm running Tiptap with Vue.js. 🎉</p>',
  19. extensions: [StarterKit],
  20. })
  21. },
  22. beforeUnmount() {
  23. this.editor.destroy()
  24. },
  25. }
  26. </script>

将其添加到你的应用

现在,替换 pages/index.vue 文件的内容,并使用 TiptapEditor 组件:

  1. <template>
  2. <div>
  3. <client-only>
  4. <tiptap-editor />
  5. </client-only>
  6. </div>
  7. </template>
  8. <script>
  9. import TiptapEditor from '~/components/TiptapEditor.vue'
  10. export default {
  11. components: {
  12. TiptapEditor,
  13. },
  14. }
  15. </script>

请注意,Tiptap 需要在客户端运行,而不是在服务器上运行。因此,你需要将编辑器组件包裹在 <client-only> 标签中。阅读更多关于客户端组件的内容。

你现在应该可以在浏览器中看到 Tiptap 了。给自己点个赞吧!:)

使用 v-model(可选)

你可能已经习惯在表单中使用 v-model 进行数据绑定,Tiptap 也支持这种方式。以下是如何在 Tiptap 中使用 v-model 的示例组件, 你可以将其集成到你的项目中:

index.vue

  1. <template>
  2. <div>
  3. <editor v-model="content" />
  4. <div class="output-group">
  5. <label>Content</label>
  6. <code>{{ content }}</code>
  7. </div>
  8. </div>
  9. </template>
  10. <script>
  11. import Editor from './Editor.vue'
  12. export default {
  13. components: {
  14. Editor,
  15. },
  16. data() {
  17. return {
  18. content: '<p>A Vue.js wrapper component for Tiptap to use <code>v-model</code>.</p>',
  19. }
  20. },
  21. }
  22. </script>
  1. <template>
  2. <editor-content :editor="editor" />
  3. </template>
  4. <script>
  5. import { Editor, EditorContent } from '@tiptap/vue-3'
  6. import StarterKit from '@tiptap/starter-kit'
  7. export default {
  8. components: {
  9. EditorContent,
  10. },
  11. props: {
  12. value: {
  13. type: String,
  14. default: '',
  15. },
  16. },
  17. data() {
  18. return {
  19. editor: null,
  20. }
  21. },
  22. watch: {
  23. value(value) {
  24. // HTML
  25. const isSame = this.editor.getHTML() === value
  26. // JSON
  27. // const isSame = JSON.stringify(this.editor.getJSON()) === JSON.stringify(value)
  28. if (isSame) {
  29. return
  30. }
  31. this.editor.commands.setContent(value, false)
  32. },
  33. },
  34. mounted() {
  35. this.editor = new Editor({
  36. content: this.value,
  37. extensions: [StarterKit],
  38. onUpdate: () => {
  39. // HTML
  40. this.$emit('input', this.editor.getHTML())
  41. // JSON
  42. // this.$emit('input', this.editor.getJSON())
  43. },
  44. })
  45. },
  46. beforeUnmount() {
  47. this.editor.destroy()
  48. },
  49. }
  50. </script>