如何绑定tiptap编辑器的内容

How to bind content of tiptap editor

我正在使用 tip-tap 编辑器,但在访问编辑器的内容时​​遇到了一些问题。 我需要 post 编辑器的内容到 API 所以我需要内容。 这是我的代码:

import tippy from "tippy.js";
import { Editor, EditorContent, VueRenderer } from "@tiptap/vue-2";
import Document from "@tiptap/extension-document";
import Paragraph from "@tiptap/extension-paragraph";
import Text from "@tiptap/extension-text";

export default {
    components: {
        EditorContent
    },

    props: {
        comment_type: String,
        comment_text: String,
        comment_id: Number,
        edit_mode: Boolean
    },

    data() {
        return {
            editor: null,
            limit: 280,
            users: [],
            comment_da: {},
            edit_comment_da: {}
        };
    },
    
    watch: {
        comment_text(value) {
            console.log(value);
            this.editor.setContent(value);
        }
    },

    mounted() {
        const self = this;
        const CustomParagraph = Paragraph.extend({
            addKeyboardShortcuts() {
                return {
                    // ↓ your new keyboard shortcut
                    "Shift-Enter": () => self.addComment()
                };
            }
        });
        this.editor = new Editor({
            extensions: [
                Document,
                CustomParagraph,
                Text,
            ],
            content: this.comment_text
        });
    },

    beforeDestroy() {
        this.editor.destroy();
    },
  }
<template>
  <div>
    <editor-content :editor="editor" class="form-control"/>
  </div>
</template>

在父组件中,我有一些 属性 需要传递给 tiptap 编辑器

import editor from "./components/editor";

new Vue({
  components: {
        editor
    },
    data() {
      comment_da: {},
      comment_text: "",
    }
})
<div class="m-messenger__form-controls">
    <editor 
        v-model="comment_text"
        :comment_text="comment_text"
        :comment_type="'comment'"
        :comment_id="comment_da.id"
    />
</div>

我无法访问编辑器内容。 我试过这个解决方案 https://github.com/ueberdosis/tiptap/issues/133 但我在输入时不断出错。

Error: "getHTML is not a function"

我找到了答案,它在 tiptap 文档中 Here

import editor from "./components/editor";

new Vue({
  components: {
        editor
    },
    data() {
      comment_da: {},
      comment_text: "",
    }
})
<div class="m-messenger__form-controls">
    <editor 
        v-model="comment_text"
        :comment_text="comment_text"
        :comment_type="'comment'"
        :comment_id="comment_da.id"
    />
</div>

import tippy from "tippy.js";
import { Editor, EditorContent, VueRenderer } from "@tiptap/vue-2";
import Document from "@tiptap/extension-document";
import Paragraph from "@tiptap/extension-paragraph";
import Text from "@tiptap/extension-text";

export default {
    components: {
        EditorContent
    },

    props: {
        comment_type: String,
        comment_text: String,
        comment_id: Number,
        edit_mode: Boolean
    },

    data() {
        return {
            editor: null,
            limit: 280,
            users: [],
            comment_da: {},
            edit_comment_da: {}
        };
    },
    
    watch: {
        comment_text(value) {
            console.log(value);
            this.editor.setContent(value);
        }
    },

    mounted() {
        const self = this;
        const CustomParagraph = Paragraph.extend({
            addKeyboardShortcuts() {
                return {
                    // ↓ your new keyboard shortcut
                    "Shift-Enter": () => self.addComment()
                };
            }
        });
        this.editor = new Editor({
            extensions: [
                Document,
                CustomParagraph,
                Text,
                Mention.configure({
                    HTMLAttributes: {
                        class: "mention"
                    },
                    suggestion: {
                        items: query => {
                            var self = this;
                            const search_user = new crud(
                                "/chat/mention/" + query
                            );
                            search_user.get_all_data(true, false, data => {
                                self.users = data.data;
                            });
                            return this.users.filter(item =>
                                item.name
                                    .toLowerCase()
                                    .startsWith(query.toLowerCase())
                            );
                        },
                        render: () => {
                            let component;
                            let popup;

                            return {
                                onStart: props => {
                                    component = new VueRenderer(MentionList, {
                                        parent: this,
                                        propsData: props
                                    });

                                    popup = tippy("body", {
                                        getReferenceClientRect:
                                            props.clientRect,
                                        appendTo: () => document.body,
                                        content: component.element,
                                        showOnCreate: true,
                                        interactive: true,
                                        trigger: "manual",
                                        placement: "bottom-start"
                                    });
                                },
                                onUpdate(props) {
                                    component.updateProps(props);

                                    popup[0].setProps({
                                        getReferenceClientRect: props.clientRect
                                    });
                                },
                                onKeyDown(props) {
                                    return component.ref?.onKeyDown(props);
                                },
                                onExit() {
                                    popup[0].destroy();
                                    component.destroy();
                                }
                            };
                        }
                    }
                })
            ],
            content: this.comment_text,
            onUpdate() {
                // You can access to both HTML and JSON type of your content
                const json = this.getJSON();
                const html = this.getHTML();
                // send the content to an API here
                this.comment_text = json.content[0].content[0].text
                    ? json.content[0].content[0].text
                    : "";
            }
        });
    },

    beforeDestroy() {
        this.editor.destroy();
    },
  }
<template>
  <div>
    <editor-content :editor="editor" class="form-control"/>
  </div>
</template>

如果您很好奇,可以查看我代码的 onUpdate 部分以获取更改。