Vue JS 可拖动编辑器未使用 Tap Tap 编辑器定义

时间:2021-03-25 13:45:42

标签: javascript html vue.js

我正在构建一个使用 Vue Draggable 库和 Tip Tap Editor 库的 Nuxt JS Web 应用程序。在我的用例中,我可以将“组件”拖到我的网页中,例如图表和编辑器。

当我将一个元素拖入我的网页时,draggable 会运行到 cloneComponent 组件上,它会计算出我拖入页面中的组件类型。

我的编辑器存储在一个单独的对象中,其中使用随机 ID 在它们之间进行通信,因为我无法直接在拖入我的页面的组件中初始化 Tip Tap 编辑器。

然而,由于某种原因,尽管我的数据存在,但我收到一个错误,其中 editor 显然无法找到,因此编辑器从未显示在我的网页上,但它确实存在,我正在努力找出原因:

<块引用>

无法读取未定义的属性“editor”

<template>
  <div>

    <!-- Report Navigation & Controls -->
    <section class="bg-white fixed inset-x-0 top-0 w-full z-40" ref="editorNavbar">
      <div v-if="!isPreviewMode" class="max-w-7xl mx-auto px-7 py-7">

        <!-- Screen: Components -->
        <div class="grid grid-cols-12">
          <div class="col-span-12">
            <draggable
              class="flex"
              :list="components"
              :group="{ name: 'components', pull: 'clone', put: false }"
              :clone="cloneComponent"
            >
              <div class="p-3 border border-4 border-gray-300 rounded-md text-center h-24 w-24 flex items-center justify-center mr-6 cursor-move" v-for="(component, index) in components" :key="index">
                <div>
                  <span v-html="component.icon"></span>
                  <span class="block mt-2 text-gray-500 text-sm font-medium">{{ component.title }}</span>
                </div>
              </div>
            </draggable>
          </div>
        </div>

      </div>
    </section>

    <!-- Report Canvas -->
    <draggable
      class="dragArea h-auto pb-96"
      :list="report"
      group="components"
    >
      <div
        v-for="(component, index) in report"
        :key="index"
      >

        <!-- Editor -->
        <!-- BUG: editors[component.componentID].editor not defined? -->
        <div v-if="component.type == 'editor'">
          <div class="mb-4">
            <div class="bg-white px-2 pt-2 pb-0">
              <editor-menu-bar :editor="editors[component.componentID].editor" v-slot="{ commands, isActive }">
                <div class="menubar">
                  <button
                    class="menubar__button w-9 h-9 p-2"
                    :class="{ 'bg-gray-100 rounded-sm': isActive.bold() }"
                    @click="commands.bold"
                  >
                    <img class="h-5 w-5 mx-auto" src="~/assets/images/icons/bold.svg" />
                  </button>
                </div>
              </editor-menu-bar>
            </div>
            <div class="bg-white rounded-md flex">
              <editor-content :editor="editors[component.componentID].editor" class="editor-box block w-full" />
            </div>
          </div>
        </div>

      </div>
    </draggable>
  </div>
</template>

<script>
import draggable from 'vuedraggable'
import { Editor, EditorContent, EditorMenuBar } from 'tiptap'
import {
  Blockquote,
  CodeBlock,
  HardBreak,
  Heading,
  OrderedList,
  BulletList,
  ListItem,
  TodoItem,
  TodoList,
  Bold,
  Code,
  Italic,
  Link,
  Strike,
  Underline,
  History
} from 'tiptap-extensions'

export default {
  layout: 'reportBuilder',
  components: {
    draggable,
    EditorMenuBar,
    EditorContent,
  },
  data () {
    return {
      id: this.$route.params.report ? this.$route.params.report : null,
      rawReport: null,
      editors: {},
      charts: [],
      report: [],
      components: [{
        title: 'Text',
        icon: '<svg class="mx-auto" xmlns="http://www.w3.org/2000/svg" fill="none" height="24" width="24" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" /></svg>',
        type: 'editor',
        name: '',
        datasets: []
      }, {
        title: 'Chart',
        icon: '<svg class="mx-auto" xmlns="http://www.w3.org/2000/svg" fill="none" height="24" width="24" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 3.055A9.001 9.001 0 1020.945 13H11V3.055z" /><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20.488 9H15V3.512A9.025 9.025 0 0120.488 9z" /></svg>',
        type: 'chart',
        name: '',
        datasets: []
      }]
    }
  },
  methods: {

    /*
    ** Clone a component into our canvas
    */
    cloneComponent ({ type, name, datasets }, compID = null) {
      const id = compID ? compID : Math.round(window.performance.now())

      // TODO: reverse and somehow get editors to show
      if (compID) {
        if (type == 'editor') {
          this.editors[id] = {
            editor: new Editor({
              extensions: [
                new Blockquote(),
                new CodeBlock(),
                new HardBreak(),
                new Heading({ levels: [1, 2, 3] }),
                new BulletList(),
                new OrderedList(),
                new ListItem(),
                new TodoItem(),
                new TodoList(),
                new Bold(),
                new Code(),
                new Italic(),
                new Link(),
                new Strike(),
                new Underline(),
                new History()
              ],
              content: '',
            }),
            content: ''
          }
        }
      }

      this.report.push({
        componentID: id ?? 0,
        type: type ?? '',
        name: name ?? '',
        datasets: datasets ?? []
      })
    },

    /*
    ** Reset report
    */
    resetReport () {
      this.rawReport = null
      this.editors = []
      this.charts = []
      this.report = []
      this.savableReport = []
      this.sourcesToFind = []
    },

    /*
    ** Get report
    */
    getReport () {
      this.resetReport()
      
      try {
        this.$axios.get(
          `${process.env.API_URL}/api/reports/view/${this.id}`,
          {
            timeout: 5000
          }
        ).then(res => {
          if (!res.data.success) return
          this.rawReport = res.data.report

          const {
            saved_at,
            discovery_filters
          } = this.rawReport

          // if there is report data linked to this report
          if (this.rawReport.report_data) {
            for (const [index, filter] of this.rawReport.report_data.entries()) {
              const clonable = {
                ...{
                  type: filter.type
                },
                ...filter
              }
              this.cloneComponent(clonable, filter.componentID)
            }
          }

          if (discovery_filters) this.sourcesToFind = discovery_filters
          this.savedAt = saved_at
        })
      } catch (err) { }
    }

  }
}
</script>

对于额外的上下文,如果 new Editor 可以只是被拖入网页的组件的一部分,那就太好了,但是在我保存我的报告后,cloneComponent 函数以及一些额外的必须运行逻辑才能检索报告数据,这就是 componentID 的用武之地。

归根结底,为什么 editor 存在于我的对象中时未定义?

0 个答案:

没有答案