Как использовать TinyMCE в Nuxt?

Я хочу добавить этот скрипт в свой код Nuxt:

<script>
  tinymce.init({
    selector: "#mytextarea",
    plugins: "emoticons",
    toolbar: "emoticons",
    toolbar_location: "bottom",
    menubar: false
  });
</script>

Я могу просто добавить его в тело шаблона моего компонента (Этот скрипт должен быть внутри <body>, а не <head>) вот так:

введите здесь описание изображения

и что интересно, это работает, но здесь есть две проблемы:

  1. это выглядит некрасиво
  2. Это не динамично. Например, я не могу динамически привязать selector к реквизиту или свойству данных! Это должно быть жестко запрограммировано.

Поэтому мне было интересно, знает ли кто-нибудь, как я могу правильно интегрировать такие скрипты в свой проект Nuxt?


person seyet    schedule 04.03.2021    source источник


Ответы (1)


  1. Я действительно очень сомневаюсь, что это работает. Vue всегда игнорирует любые теги <script> в шаблонах с сообщением об ошибке:

Шаблоны должны отвечать только за сопоставление состояния с пользовательским интерфейсом. Избегайте размещения в шаблонах тегов с побочными эффектами, таких как <script>, так как они не будут проанализированы.

  1. Нет причин помещать это в шаблон. Это обычный JS-код, который вы можете выполнять как часть жизненного цикла компонента. Ниже приведена очень простая оболочка компонента, которая интегрирует TinyMCE в приложение Vue.

Однако я не рекомендую делать это самостоятельно и вместо этого использовать официальную оболочку Vue (документы) — используйте v3 для Vue 2. Официальная интеграция обрабатывает все крайние случаи, такие как активация/деактивация компонента (при использовании вместе с <keep-alive>) и правильная очистка при уничтожении компонента, что необходимо для предотвращения неприятных утечек памяти

const ed = Vue.component("MyEditor", {
  props: ["id", "value"],
  template: `
    <div>
      <textarea :id="id" :value="value"></textarea>
    </div>
  `,
  mounted() {
    const me = this;
    window.tinymce.init({
      selector: "#" + this.id,
      plugins: "emoticons",
      toolbar: "emoticons",
      toolbar_location: "bottom",
      menubar: false,
      setup: function (editor) {
        editor.on("change input undo redo", function () {
          me.$emit('input', editor.getContent({format: 'text'}))
        });
      }
    });
  }
});

Демо

Nuxt

Поскольку TinyMCE полностью рендерится с помощью JS, нет смысла выполнять его во время рендеринга на стороне сервера. Фактически, приведенный выше код вообще не будет работать на сервере, так как нет переменной window. Используйте <client-only> компонент Nuxt, чтобы Nuxt для рендеринга редактора только на клиенте...

ОБНОВЛЕНИЕ: С другой стороны, хук жизненного цикла mounted вообще не вызывается во время SSR, поэтому, возможно, это будет работать нормально даже без <client-only>

person Michal Levý    schedule 04.03.2021
comment
Это действительно сработало. Спасибо. Однако не могли бы вы дать мне объяснение части setup: function (editor)? Что он делает и зачем нам его туда добавлять? - person seyet; 09.03.2021
comment
Да, я знаю, что это работает, но, как я уже сказал, не используйте мой код. Отсутствует очень важная часть - уничтожение редактора при уничтожении компонента. Я мог бы добавить его, но кажется пустой тратой времени, если есть официальная интеграция для Vue от авторов TinyMCE. Они лучше знают своего редактора... - person Michal Levý; 09.03.2021
comment
setup — это функция, вызываемая TinyMCE. Это полезно для настройки обработчиков событий. В моем примере я обрабатываю события, генерируемые при изменении содержимого редактора, чтобы генерировать событие Vue input — это заставляет v-model работать с компонентом... - person Michal Levý; 09.03.2021
comment
Ага имеет смысл. Есть еще скрипты из других источников, которые я хочу интегрировать, большинство из которых не имеют официальной интеграции с Vue. Как вы предлагаете мне продолжить их интеграцию? - person seyet; 10.03.2021