Самый простой способ использовать интегрированный UEditor в проектах Vue, включая загрузку изображений.

внешний интерфейс Vue.js
Самый простой способ использовать интегрированный UEditor в проектах Vue, включая загрузку изображений.

Постоянная ссылка на эту статью:GitHub.com/H AOC также 942…

Ссылка на проект Vue 3здесь

предисловие

обложкаUEditorизИндекс Байдулинейный график. Хотя на дворе 2018 год и есть много хороших форматированных текстовых редакторов (в том числе мобильных), это видно по картинкеUEditorПо-прежнему сохраняя высокую поисковую популярность. И многие компании и частные лица до сих пор используют его в проекте.UEditor. В настоящее время,UEditorПоследнее обновление версии официального сайта было1.4.3.3, это уже вещь в 2016 году, а сегодняшняя front-end разработка, многие мелкие партнеры используютVue,ReactЭто компонентный интерфейсный фреймворк. Это приводит к интеграции в эти «современные» рамки.UEditorстановится очень грубым. Поэтому будет много представлений, таких как следующие фотографии.Vueинтеграция в проектUEditorблог:

В целях повышения возможности повторного использования кода, а также для того, чтобы сервисный код не был легированUEditorсвязанных операций, я создал компонент в разработке проекта компании несколько месяцев назад, доступ к которому можно получить черезv-modelдвусторонняя привязкаUEditor, так же просто, как использоватьinputкоробка. Когда я закончил, я почувствовал себя оченьVueперсонаж. И я читаю много блогов иGitHubпроекта, аналогичной реализации нет. Поэтому я решил опубликовать вnpmПомощь общественности, все еще думающей о том, какUEditorР ГVueпартнеров по проекту. Через несколько месяцев он в основном стабилизировался, поэтому сегодня я поделюсь им с вами через этот блог.

Первый взгляд на визуализацию:

Нажмите, чтобы просмотреть Адрес склада

Installation

npm i vue-ueditor-wrap
# 或者
yarn add vue-ueditor-wrap

Quick Start

Полная ДЕМО на основе vue-cli 2.x
Рендеринг на стороне сервера на основе Nuxt DEMO.

  1. скачатьUEditor

    скачатьПоследний скомпилированный UEditor. Последняя версия официального сайта1.4.3.3, есть много ошибок, таких какIssue1, а официальная уже активно не поддерживается. Для мира во всем мире, для некоторых распространенных ошибок, я выполнилремонт, и поместите скомпилированные файлы в репозиторийassets/downloadsкаталог, можете не сомневатьсяскачать, конечно, вы также можетеclone Официальный исходный кода такжекомпилировать.

    Разархивируйте загруженный zip и переименуйте его вUEditor(Мне нужно только выбрать нужную вам версию, напримерutf8-php), введите свой проектstaticПод содержанием.

    если вы используетеvue-cli 3.x, вы можете поставитьUEditorпапку в папку проектаpublicПод содержанием.

  2. представлятьVueUeditorWrapкомпоненты

    import VueUeditorWrap from 'vue-ueditor-wrap' // ES6 Module
    // 或者
    const VueUeditorWrap = require('vue-ueditor-wrap') // CommonJS
    

    Вы также можете импортировать напрямую,CDNприкован, он раскрывает глобальнуюVueUeditorWrapПеременные (как использовать вы можете прочитать в моей статьеблогили обратитесь к этомусклад).

    <script src="https://cdn.jsdelivr.net/npm/vue-ueditor-wrap@latest/lib/vue-ueditor-wrap.min.js"></script>
    
  3. Регистрация компонентов

    components: {
      VueUeditorWrap
    }
    // 或者在 main.js 里将它注册为全局组件
    Vue.component('vue-ueditor-wrap', VueUeditorWrap)
    
  4. v-modelпривязать данные

    <vue-ueditor-wrap v-model="msg"></vue-ueditor-wrap>
    
    data () {
      return {
        msg: '<h2>Vue + UEditor + v-model双向绑定</h2>'
      }
    }
    

    На данный момент вы уже можете видеть инициализацию на страницеUEditor, и это было успешно связано с данными! 👏👏👏

  5. Измените конфигурацию в соответствии с требованиями проекта, просмотрите полные параметры конфигурацииueditor.config.jsисходный код илиофициальная документация

    <vue-ueditor-wrap v-model="msg" :config="myConfig"></vue-ueditor-wrap>
    
    data () {
      return {
        msg: '<h2>Vue + UEditor + v-model双向绑定</h2>',
        myConfig: {
          // 编辑器不自动被内容撑高
          autoHeightEnabled: false,
          // 初始容器高度
          initialFrameHeight: 240,
          // 初始容器宽度
          initialFrameWidth: '100%',
          // 上传文件接口(这个地址是我为了方便各位体验文件上传功能搭建的临时接口,请勿在生产环境使用!!!)
          serverUrl: '//ueditor.szcloudplus.com/cos',
          // UEditor 资源文件的存放路径,如果你使用的是 vue-cli 生成的项目,通常不需要设置该选项,vue-ueditor-wrap 会自动处理常见的情况,如果需要特殊配置,参考下方的常见问题2
          UEDITOR_HOME_URL: '/static/UEditor/'
        }
      }
    }
    

Advanced

  1. Как получитьUEditorпример?

    <vue-ueditor-wrap @ready="ready"></vue-ueditor-wrap>
    
    methods: {
      ready (editorInstance) {
        console.log(`编辑器实例${editorInstance.key}: `, editorInstance)
      }
    }
    
  2. Находится ли параметр в компонентеbeforeDestroyУничтожить на крючкеUEditorПример

    <vue-ueditor-wrap :destroy="true"></vue-ueditor-wrap>
    
  3. Выбратьv-modelспособ реализации. Реализация двусторонней привязки зависит от мониторинга изменений содержимого редактора.Из-за разных методов мониторинга будут различия в эффектах мониторинга.Вы можете выбрать сами, но рекомендуется использовать нестандартный значения по умолчанию для коробки.

    <vue-ueditor-wrap mode="listener"></vue-ueditor-wrap>
    

    Дополнительные значения:observer,listener

    По умолчанию:observer

    Описание параметра:

    1. observerшаблонMutationObserver API. Преимуществом является точность прослушивания, недостатком — небольшая дополнительная нагрузка на производительность. ты можешь пройтиobserverDebounceTimeСвойство устанавливает интервал срабатывания, и вы также можете передатьobserverOptionsВыборочные настройки свойствMutationObserverнаблюдение за поведением. API совместим только с IE11+, ноvue-ueditor-wrapбудет автоматически включен в неподдерживаемых браузерахlistenerмодель.

      <vue-ueditor-wrap
        mode="observer"
        :observerDebounceTime="100"
        :observerOptions="{ attributes: true, characterData: true, childList: true, subtree: true }"
        >
      </vue-ueditor-wrap>
      
    2. listenerрежим с помощью UEditorсобытие contentChange, преимущество в том, что он опирается на официальный API событий, не требуется дополнительного потребления производительности, и совместимость лучше, но недостаток в том, что точность мониторинга не высока, и есть ОШИБКИ, упомянутые в следующем [FAQ 5] .

  4. служба поддержкиVue SSR?

    поскольку2.4.0Версия начинает поддерживать рендеринг на стороне сервера! Этот компонент обеспечиваетNuxtПроекты поддерживаются из коробки. Но если вы построите его самиVue SSRпроекта, вам может потребоваться различать серверную и клиентскую среды и комбинироватьforceInitСвойство является обязательным для инициализации редактора, но есть большая вероятность, что вы не будете использовать это свойство, даже если это проект SSR, созданный вами, дополнительные вопросы приветствуются при отправке ISSUE.

  5. Как осуществить вторичную разработку (добавить пользовательские кнопки, всплывающие окна и т.д.)?

    Этот компонент обеспечиваетbeforeInitкрючок, он будет вUEditorПосле загрузки скриптов и до инициализации редактора вы можете выполнять вторичную разработку, например добавлять пользовательские кнопки, всплывающие окна и т. д., манипулируя в это время объектом window.UE.beforeInitФункция триггера принимает идентификатор редактора и параметры конфигурации в качестве входных параметров. Ниже приведен пример простой пользовательской кнопки и пользовательского всплывающего окна.DEMOПример настройки кнопки "Центр таблиц" также представлен на складе. Если у вас есть дополнительные потребности во вторичной разработке, вы можете обратиться кОфициальный APIилиИсходный код UEditorпример в .

    Пользовательская кнопка Демо
    <vue-ueditor-wrap v-model="msg" @beforeInit="addCustomButtom"></vue-ueditor-wrap>
    
    addCustomButtom (editorId) {
      window.UE.registerUI('test-button', function (editor, uiName) {
        // 注册按钮执行时的 command 命令,使用命令默认就会带有回退操作
        editor.registerCommand(uiName, {
          execCommand: function () {
            editor.execCommand('inserthtml', `<span>这是一段由自定义按钮添加的文字</span>`)
          }
        })
    
        // 创建一个 button
        var btn = new window.UE.ui.Button({
          // 按钮的名字
          name: uiName,
          // 提示
          title: '鼠标悬停时的提示文字',
          // 需要添加的额外样式,可指定 icon 图标,图标路径参考常见问题 2
          cssRules: "background-image: url('/test-button.png') !important;background-size: cover;",
          // 点击时执行的命令
          onclick: function () {
            // 这里可以不用执行命令,做你自己的操作也可
            editor.execCommand(uiName)
          }
        })
    
        // 当点到编辑内容上时,按钮要做的状态反射
        editor.addListener('selectionchange', function () {
          var state = editor.queryCommandState(uiName)
          if (state === -1) {
            btn.setDisabled(true)
            btn.setChecked(false)
          } else {
            btn.setDisabled(false)
            btn.setChecked(state)
          }
        })
    
        // 因为你是添加 button,所以需要返回这个 button
        return btn
      }, 0 /* 指定添加到工具栏上的哪个位置,默认时追加到最后 */, editorId /* 指定这个 UI 是哪个编辑器实例上的,默认是页面上所有的编辑器都会添加这个按钮 */)
    }
    
    Демонстрация пользовательского всплывающего окна
    <vue-ueditor-wrap v-model="msg" @beforeInit="addCustomDialog"></vue-ueditor-wrap>
    
    addCustomDialog (editorId) {
      window.UE.registerUI('test-dialog', function (editor, uiName) {
        // 创建 dialog
        var dialog = new window.UE.ui.Dialog({
          // 指定弹出层中页面的路径,这里只能支持页面,路径参考常见问题 2
          iframeUrl: '/customizeDialogPage.html',
          // 需要指定当前的编辑器实例
          editor: editor,
          // 指定 dialog 的名字
          name: uiName,
          // dialog 的标题
          title: '这是一个自定义的 Dialog 浮层',
          // 指定 dialog 的外围样式
          cssRules: 'width:600px;height:300px;',
          // 如果给出了 buttons 就代表 dialog 有确定和取消
          buttons: [
            {
              className: 'edui-okbutton',
              label: '确定',
              onclick: function () {
                dialog.close(true)
              }
            },
            {
              className: 'edui-cancelbutton',
              label: '取消',
              onclick: function () {
                dialog.close(false)
              }
            }
          ]
        })
    
        // 参考上面的自定义按钮
        var btn = new window.UE.ui.Button({
          name: 'dialog-button',
          title: '鼠标悬停时的提示文字',
          cssRules: `background-image: url('/test-dialog.png') !important;background-size: cover;`,
          onclick: function () {
            // 渲染dialog
            dialog.render()
            dialog.open()
          }
        })
    
        return btn
      }, 0 /* 指定添加到工具栏上的那个位置,默认时追加到最后 */, editorId /* 指定这个UI是哪个编辑器实例上的,默认是页面上所有的编辑器都会添加这个按钮 */)
    }
    

    HTML-страница во всплывающем слоеcustomizeDialogPage.html

    <!DOCTYPE html>
    <html>
    
    <head>
      <meta charset="UTF-8">
      <title>Title</title>
      <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
      <meta name="renderer" content="webkit">
      <!--页面中一定要引入internal.js为了能直接使用当前打开dialog的实例变量-->
      <!--internal.js默认是放到 UEditor/dialogs 目录下的-->
      <script type="text/javascript" src="./UEditor/dialogs/internal.js"></script>
    </head>
    
    <body>
      <h1>hello vue-ueditor-wrap</h1>
      <script>
        //可以直接使用以下全局变量
        //当前打开dialog的实例变量
        console.log('editor: ' + editor);
        //一些常用工具
        console.log('domUtils: ' + domUtils);
        console.log('utils: ' + utils);
        console.log('browser: ' + browser);
        dialog.onok = function() {
          editor.execCommand('inserthtml', '<span>我点击了确定</span>');
        };
        dialog.oncancel = function() {
          editor.execCommand('inserthtml', '<span>我点击了取消</span>');
        };
      </script>
    </body>
    
    </html>
    

Features

  1. v-modelДвусторонняя привязка данных! Вам не нужно думать о создании экземпляра, и вам не нужно думать о том, когдаgetContent,когдаsetContent, так же просто, как использоватьinputТа самая коробка!

  2. полностью соответствует официальномуAPI, все параметры конфигурации и методы инстанса точно такие же, как и официальные. Даваяvue-ueditor-wrapкомпонентconfigсвойство передать объект, вы можете получить полностью независимую конфигурациюUEditorредактор. слушаяreadyсобытие, которое вы можете получить инициализированнымUEditorэкземпляр и выполнять различные методы на экземпляре.

  3. Автоматически добавлять зависимые файлы. тебе не нужно бытьindex.htmlилиmain.jsВведениеUEditorJS-файл. Что еще более важно, даже если вы используете несколькоvue-ueditor-wrapКомпоненты, файлы JS, от которых они зависят, будут загружены только один раз. Причина этого в том, что вам не нужно загружать много файлов, как только пользователь открывает проект.UEditorсвязанные ресурсы, все файлы ресурсов будут найдены только вvue-ueditor-wrapКомпонент загружается только при первой активации. Конечно, если выindex.htmlилиmain.jsвводятся сопутствующие ресурсы,vue-ueditor-wrapОн также будет точно судить, и вам не придется беспокоиться о его перезагрузке.

  4. каждыйvue-ueditor-wrapКомпоненты полностью независимы. Вы даже можете использовать наv-forИнструкции по рендерингу 99 Tuskis за раз (не забудьте добавитьkeyстоимость).

FAQ (часто задаваемые вопросы)

  1. служба поддержкиIEЖдать более ранней версии браузера?

    а такжеVueто же, общая поддержкаIE9+👏👏👏

  2. Почему я вижу эту ошибку?

    ЭтоUEDITOR_HOME_URLВызвано неправильной конфигурацией параметров. Используйте этот компонент в проекте, сгенерированном vue cli 2.x, значение по умолчанию —'/static/UEditor/', в проекте, сгенерированном vue cli 3.x, значение по умолчанию равноprocess.env.BASE_URL + 'UEditor/'.但这并不能满足所有情况。例如你的项目不是部署在网站根目录下,如"http://www.example.com/my-app/", вам может потребоваться установить"/my-app/static/UEditor/". Используются ли относительные пути и используется ли маршрутизацияhistoryРежимы, правильно ли настроен сервер и т. д. — все это может иметь значение. Подводя итог: как локальная разработка, так и развертывание на сервере, что бы вы ни указалиUEditorФайл ресурсов должен быть реальным,vue-ueditor-wrapОн также выводит полный путь к файлу ресурсов, который он пытается загрузить через консоль, когда JS не загружается, поэтому вы можете проанализировать, как его заполнить. Когда пришло время различать среды, вы можете судить поprocess.env.NODE_ENVустанавливаться отдельно.

  3. Как загрузить изображения и файлы? почему я вижу后台配置项返回格式出错?

    Такие функции, как загрузка изображений и файлов, должны взаимодействовать с фоном, и вы не даетеconfigсвойство передано правильноserverUrl, я предоставил//ueditor.szcloudplus.com/cosвременный интерфейс, который можно использовать для тестирования,Но не используйте его в производственной среде! ! !Чтобы узнать, как создать интерфейс загрузки, см.официальная документация.

  4. Не удалось загрузить одно изображение между доменами!

    UEditorЗагрузка одиночного изображения реализована через форму + iframe, но из-за ограничения политики одного и того же источника родительская страница не может получить доступ к содержимому документа междоменного iframe, поэтому возникнет проблема междоменная загрузка изображения не удалась. Я реорганизовал способ загрузки одного изображения через XHR,Загрузите последний скомпилированный UEditorфайлы ресурсов можно найти вIE10+Браузер реализует единую междоменную загрузку графа. подробности,Нажмите здесь, чтобы просмотреть. Конечно, вы также можете настроитьtoolbarsПараметры для скрытия кнопки загрузки одного изображения в сочетании с «пользовательской кнопкой», представленной выше, кривая сохраняет страну, следующий код только для справки.

    var input = document.createElement('input')
    input.type = "file"
    input.style.display = 'none'
    document.body.appendChild(input)
    input.click()
    input.addEventListener('change',(e)=>{
        // 利用 AJAX 上传,上传成功之后销毁 DOM
        console.log(e.target.files)
    })
    
  5. почему я набрал"? ! $ #"Эти специальные символы не связаны успешно?

    когда вы используетеlistenerВо время режима, из-заv-modelРеализация основана наUEditorпримерcontentChangeМониторинг событий, и вы обычно нажимаете и удерживаете при вводе этих специальных символовshiftключ,UEditorсебяcontentChangeсуществуетshiftОн не срабатывает при удерживании клавиши, вы также можете попробовать нажать несколько клавиш одновременно, и вы обнаружитеcontentChangeЗапустился только один раз. вы можете использоватьobserverузор или движениеUEditor.

  6. После загрузки одного изображенияv-modelсвязанloadingМаленький значок.

    это тожеUEditorизBUG. Моя последняя отредактированная версия, исправляющая официальнуюBUG, если вы используете файл ресурсов, загруженный с официального сайта, замените файл ресурсов или обратитесь кIssue1.

Дополнительные вопросы, добро пожаловать, чтобы представитьISSUEили пойтичатЗадавать вопросы.但由于这是一个个人维护的项目,我平时也有自己的工作,所以并不能保证及时解决你们的所有问题,如果小伙伴们有好的建议或更炫酷的操作,也欢迎PR, если вы считаете, что этот компонент действительно удобен для вашей разработки, большое спасибоStar, и конечно же кофе:

Модификация кода, пожалуйста, следуйте указаннымESLintправило,PRпожалуйста, выполните доnpm run lintВыполните определение стиля кода, большинство деталей синтаксиса могут быть переданы черезnpm run fixИсправление, после сборки не забудьте изменитьpackage.jsonНомер версии в нем мне удобенReviewОпубликовано сообщением Ma Yoyo вnpm.

Суммировать

Хотя это небольшое новшество,UEditorИли, может быть, устаревший редактор форматированного текста. Но, поддерживая этот проект и помогая группе мелких партнеров решитьISSUEВ процессе я сильно вырос. Что меня больше всего впечатляет, так это то, что многие друзья также прислали благодарственные письма на мой почтовый ящик, и я также обнаружил, что некоторые люди уже начали использовать его в проекте. Радость быть признанным другими и помогать другим по-настоящему известна только тем, кто испытал это на себе. Не так давно я решил начать вести блог на Наггетс.Хотя некоторые вещи не так хорошо написаны, или у меня неправильное восприятие, всегда есть группа восторженных и отличных друзей, которые поправят и дадут в комментариях. совет. Делиться приятно! Поэтому эту мою статью тоже стоит использовать как путеводитель.Если у вас есть хорошие предложения или крутые операции, тоже милости просим.PR,ноPRпожалуйста, выполните доnpm run lintДля определения стиля кода большинство сведений о синтаксисе также можно передать черезnpm run fixИсправление, также не забудьте изменитьpackage.jsonномер версииversion, так что я могу публиковать прямо вnpm. Конечно, если у вас есть полезный редактор форматированного текста, вы также можете порекомендовать его в области комментариев.