TinyMce 在滑入元素内加载时破坏 TailwindCss 动画

TinyMce breaking TailwindCss animation when loaded inside a slide-over element

我有一个简单的 Vue3 应用程序,它大量使用 TailwindUI 组件。我正在尝试将 TinyMce 编辑器放置在滑过组件内并且工作正常。问题是入口动画。

第一次进入时,它会像预期的那样滑入。但是,如果它被关闭并重新打开,进入动画就消失了。退出动画在整个过程中继续正常工作。有什么方法可以做到这一点并保持动画完好无损吗?

这里是 CodeSandBox 以最简单的形式重现了问题。

相关代码如下: App.vue

<template>
  <button @click="open = true">Open Menu</button>
  <SlideOver :open="open" @close="open = false" />
</template>

<script>
import { ref } from "vue";
import SlideOver from "./components/slide-over.vue";

export default {
  name: "App",
  components: {
    SlideOver,
  },
  setup() {
    const open = ref(false);

    return { open };
  },
};
</script>

幻灯片-over.vue

<!-- This example requires Tailwind CSS v2.0+ -->
<template>
  <TransitionRoot as="template" :show="open">
    <Dialog
      as="div"
      static
      class="fixed inset-0 overflow-hidden"
      @close="$emit('close')"
      :open="open"
    >
      <div class="absolute inset-0 overflow-hidden">
        <DialogOverlay class="absolute inset-0" />

        <div class="fixed inset-y-0 right-0 pl-10 max-w-full flex">
          <TransitionChild
            as="template"
            enter="transform transition ease-in-out duration-500 sm:duration-700"
            enter-from="translate-x-full"
            enter-to="translate-x-0"
            leave="transform transition ease-in-out duration-500 sm:duration-700"
            leave-from="translate-x-0"
            leave-to="translate-x-full"
          >
            <div class="w-screen max-w-md">
              <div
                class="h-full flex flex-col py-6 bg-white shadow-xl overflow-y-scroll"
              >
                <div class="px-4 sm:px-6">
                  <div class="flex items-start justify-between">
                    <DialogTitle class="text-lg font-medium text-gray-900">
                      Panel title
                    </DialogTitle>
                    <div class="ml-3 h-7 flex items-center">
                      <button
                        class="bg-white rounded-md text-gray-400 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
                        @click="$emit('close')"
                      >
                        <span class="sr-only">Close panel</span>
                        <XIcon class="h-6 w-6" aria-hidden="true" />
                      </button>
                    </div>
                  </div>
                </div>
                <div class="mt-6 relative flex-1 px-4 sm:px-6">
                  <TinyMceEditor api-key="no-api-key" />
                </div>
              </div>
            </div>
          </TransitionChild>
        </div>
      </div>
    </Dialog>
  </TransitionRoot>
</template>

<script>
import {
  Dialog,
  DialogOverlay,
  DialogTitle,
  TransitionChild,
  TransitionRoot,
} from "@headlessui/vue";
import { XIcon } from "@heroicons/vue/outline";
import TinyMceEditor from "@tinymce/tinymce-vue";

export default {
  components: {
    Dialog,
    DialogOverlay,
    DialogTitle,
    TransitionChild,
    TransitionRoot,
    XIcon,
    TinyMceEditor,
  },
  props: {
    open: {
      type: Boolean,
      default: false,
    },
  },
  setup() {},
};
</script>

在我看来,这是加载TinyMce Editor 的问题(我不知道到底是什么问题)。我在使用 watchEffect 打开模式后加载编辑器时添加了延迟,基于道具 opensetTimeoutv-ifTinyMceEditor 标签上。这可能不是一个完美且美观的解决方案,但动画效果很流畅。

这里是code in codesandbox.io.

此处代码:slide-over.vue(App.vue保持不变)

<template>
  <TransitionRoot as="template" :show="open">
    <Dialog
      as="div"
      static
      class="fixed inset-0 overflow-hidden"
      @close="$emit('close')"
      :open="open"
    >
      <div class="absolute inset-0 overflow-hidden">
        <DialogOverlay class="absolute inset-0" />

        <div class="fixed inset-y-0 right-0 pl-10 max-w-full flex">
          <TransitionChild
            as="template"
            enter="transform transition ease-in-out duration-500 sm:duration-700"
            enter-from="translate-x-full"
            enter-to="translate-x-0"
            leave="transform transition ease-in-out duration-500 sm:duration-700"
            leave-from="translate-x-0"
            leave-to="translate-x-full"
          >
            <div class="w-screen max-w-md">
              <div
                class="h-full flex flex-col py-6 bg-white shadow-xl overflow-y-scroll"
              >
                <div class="px-4 sm:px-6">
                  <div class="flex items-start justify-between">
                    <DialogTitle class="text-lg font-medium text-gray-900">
                      Panel title
                    </DialogTitle>
                    <div class="ml-3 h-7 flex items-center">
                      <button
                        class="bg-white rounded-md text-gray-400 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
                        @click="$emit('close')"
                      >
                        <span class="sr-only">Close panel</span>
                        <XIcon class="h-6 w-6" aria-hidden="true" />
                      </button>
                    </div>
                  </div>
                </div>
                <div class="mt-6 relative flex-1 px-4 sm:px-6">
                  <TinyMceEditor v-if="loadEditor" api-key="no-api-key" />
                </div>
              </div>
            </div>
          </TransitionChild>
        </div>
      </div>
    </Dialog>
  </TransitionRoot>
</template>
<script>
import { ref, watchEffect } from "vue";
import {
  Dialog,
  DialogOverlay,
  DialogTitle,
  TransitionChild,
  TransitionRoot,
} from "@headlessui/vue";
import { XIcon } from "@heroicons/vue/outline";
import TinyMceEditor from "@tinymce/tinymce-vue";

export default {
  components: {
    Dialog,
    DialogOverlay,
    DialogTitle,
    TransitionChild,
    TransitionRoot,
    XIcon,
    TinyMceEditor,
  },
  props: {
    open: {
      type: Boolean,
      default: false,
    },
  },
  setup(props) {
    const loadEditor = ref(false);
    watchEffect(() => {
      if (props.open) {
        setTimeout(function () {
          loadEditor.value = true;
        }, 10);
      } else {
        loadEditor.value = false;
      }
    });
    return { loadEditor };
  }
};
</script>