Collect the use of different rich text editors (vue3 version)

Article directory

  • 1. ueditor (Baidu Rich Text Editor)
    • Install
    • Use and re-package components
  • 2. KindEditor
    • download file
    • Create new components and use them

1. ueditor (Baidu Rich Text Editor)

Reference ueditor and vue-ueditor-wrap
The encapsulated vue component is used directly here vue-ueditor-wrap vue3 version

Installation

npm i [email protected] -S
or
yarn add [email protected]

Use and re-encapsulate components

  • main.ts
import VueUeditorWrap from 'vue-ueditor-wrap';
import App from '@/App/index.vue';
const app = createApp(App).use(VueUeditorWrap)
  • ueditor/index.vue
<template>
  <vue-ueditor-wrap
    v-model="content"
    :config="VueUeditorWrapConfig"
    :editor-id="editorId"
  ></vue-ueditor-wrap>
</template>
<script>
import {<!-- --> default as VueUeditorWrapConfig } from "./ueditor.js";
import {<!-- --> RandomNumber } from '@/utils'
export default {<!-- -->
  props: {<!-- -->
    value: [String],
    property: {<!-- -->
      type: Object,
      default() {<!-- -->
        return {<!-- -->};
      },
    },
  },
  model: {<!-- -->
    prop: "value", // Specify the name of the parameter to be bound by v-model, which comes from the parameters defined in props
    event: "change", // Specify the event name to be triggered, which will be used for $emit
  },
  data() {<!-- -->
    return {<!-- -->
      show: false,
      VueUeditorWrapConfig,
      isPosting: false,
      edit_show: true,
      index: 0,
      editorId: 'editor' + RandomNumber()
    };
  },
  computed: {<!-- -->
    content: {<!-- -->
      get() {<!-- -->
        return this.value;
      },
      set(val) {<!-- -->
        this.$emit("change", val);
      },
    },
  },
};
</script>
<style lang="less" scoped>
/* Pop-up input box length */
.lengthWidth {<!-- -->
  width: 80%;
}

.editor_if {<!-- -->
  width: 100%;
  height: 400px;
}

.edui1 {<!-- -->
  z-index: 90 !important;
}
</style>

  • ueditor/ueditor.js
// let env = process.env.NODE_ENV || ''
let ueditorPath = ''
// if (env === 'development') {<!-- -->
// ueditorPath = '/static/UEditor/'
// } else if (env === 'production') {<!-- -->
// ueditorPath = '/static/UEditor/'
// } else {<!-- -->
// ueditorPath = '/static/UEditor/'
// }
ueditorPath = '/ueditor/'
export default {<!-- -->
  UEDITOR_HOME_URL: ueditorPath,
  maximumWords: 1000 * 100,
  // toolbars: [
  //[
  // 'source', '|', 'undo', 'redo', '|',
  // 'bold', 'italic', 'underline', 'fontborder', 'strikethrough', 'superscript', 'subscript', 'removeformat', 'formatmatch', 'autotypeset', 'blockquote', 'pasteplain', '|', 'forecolor', 'backcolor', 'insertorderedlist', ' insertunorderedlist', 'selectall', 'cleardoc', '|',
  // 'rowspacingtop', 'rowspacingbottom', 'lineheight', '|',
  // 'customstyle', 'paragraph', 'fontfamily', 'fontsize', '|',
  // 'directionalityltr', 'directionalityrtl', 'indent', '|',
  // 'justifyleft', 'justifycenter', 'justifyright', 'justifyjustify', '|', 'touppercase', 'tolowercase', '|',
  // 'imagenone', 'imageleft', 'imageright', 'imagecenter', '|',
  // 'horizontal', 'date', 'time',
  // 'inserttable', 'simpleupload', 'preview',
  // ]
  // ],
  toolbars: [
    [
      'source', '|', 'undo', 'redo', '|',
      'bold', 'italic', 'underline', 'fontborder', 'strikethrough', 'superscript', 'subscript', 'removeformat', ' formatmatch', 'autotypeset', 'blockquote', 'pasteplain', '|', 'forecolor', 'backcolor', 'insertorderedlist', 'insertunorderedlist\ ', 'selectall', 'cleardoc', '|',
      'rowspacingtop', 'rowspacingbottom', 'lineheight', '|',
      'customstyle', 'paragraph', 'fontfamily', 'fontsize', '|',
      'directionalityltr', 'directionalityrtl', 'indent', '|',
      'justifyleft', 'justifycenter', 'justifyright', 'justifyjustify', '|', 'touppercase', 'tolowercase', '|',
      'imagenone', 'imageleft', 'imageright', 'imagecenter', '|',
      'horizontal'
    ]
  ],
  enableAutoSave: false,
  elementPathEnabled: false,
  disabledTableInTable: false,
  serverUrl: '' // No interface yet APP_CONFIG.baseURL + '/file/upload'
}

Using the above defined components can display the following effect:

2. KindEditor

Download file

kindeditor

Place in local static directory

New components and usage

Create the following folders and files in the component folder

  • kind-editor/index.vue
<template>
  <div class="kindeditor">
    <textarea :id="id" name="content" v-model="state.outContent"></textarea>
  </div>
</template>
  
<script lang="ts">

import {<!-- --> defineComponent, onMounted, reactive, watch } from "vue"
import '@public/kind-editor/themes/default/default.css'
import '@public/kind-editor/kindeditor-all.js'
import '@public/kind-editor/lang/zh-CN.js'
import '@public/kind-editor/lang/en.js'
export default defineComponent({<!-- -->
  name: 'kind-editor',
  props: {<!-- -->
    modelValue: {<!-- -->
      type: String,
      default: ''
    },
    id: {<!-- -->
      type: String,
      required: true
    },
    width: {<!-- -->
      type: String
    },
    height: {<!-- -->
      type: String
    },
    minWidth: {<!-- -->
      type: Number,
      default: 650
    },
    minHeight: {<!-- -->
      type: Number,
      default: 100
    },
    items: {<!-- -->
      type: Array,
      default: function () {<!-- -->
        return [
          'source', '|', 'undo', 'redo', '|', 'preview', 'print', 'code', ' cut', 'copy', 'paste',
          'plainpaste', 'wordpaste', '|', 'justifyleft', 'justifycenter', 'justifyright',
          'justifyfull', 'insertorderedlist', 'insertunorderedlist', 'indent', 'outdent', 'subscript',
          'superscript', 'clearhtml', 'quickformat', 'selectall', '|', 'fullscreen', '/',
          'formatblock', 'fontname', 'fontsize', '|', 'forecolor', 'hilitecolor', 'bold',
          'italic', 'underline', 'strikethrough', 'lineheight', 'removeformat', '|', 'image',
          'media', 'insertfile', 'table', 'hr', 'pagebreak',
          'anchor', 'link', 'unlink',
        ]
      }
    },
    noDisableItems: {<!-- -->
      type: Array,
      default: function () {<!-- -->
        return ['source', 'fullscreen']
      }
    },
    filterMode: {<!-- -->
      type: Boolean,
      default: true
    },
    htmlTags: {<!-- -->
      type: Object,
      default: function () {<!-- -->
        return {<!-- -->
          font: ['color', 'size', 'face', '.background-color'],
          span: ['style'],
          div: ['class', 'align', 'style'],
          table: ['class', 'border', 'cellspacing', 'cellpadding', 'width', 'height', 'align', 'style' ],
          'td,th': ['class', 'align', 'valign', 'width', 'height', 'colspan', 'rowspan' , 'bgcolor', 'style'],
          a: ['class', 'href', 'target', 'name', 'style'],
          embed: ['src', 'width', 'height', 'type', 'loop', 'autostart', 'quality',
            'style', 'align', 'allowscriptaccess', '/'],
          img: ['src', 'width', 'height', 'border', 'alt', 'title', 'align', 'style' , '/'],
          hr: ['class', '/'],
          br: ['/'],
          'p,ol,ul,li,blockquote,h1,h2,h3,h4,h5,h6': ['align', 'style'],
          'tbody,tr,strong,b,sub,sup,em,i,u,strike': []
        }
      }
    },
    wellFormatMode: {<!-- -->
      type: Boolean,
      default: true
    },
    resizeType: {<!-- -->
      type: Number,
      default: 2
    },
    themeType: {<!-- -->
      type: String,
      default: 'default'
    },
    langType: {<!-- -->
      type: String,
      default: 'en'
    },
    designMode: {<!-- -->
      type: Boolean,
      default: true
    },
    fullscreenMode: {<!-- -->
      type: Boolean,
      default: false
    },
    basePath: {<!-- -->
      type: String
    },
    themesPath: {<!-- -->
      type: String
    },
    pluginsPath: {<!-- -->
      type: String,
      default: ''
    },
    langPath: {<!-- -->
      type: String
    },
    minChangeSize: {<!-- -->
      type: Number,
      default: 5
    },
    loadStyleMode: {<!-- -->
      type: Boolean,
      default: true
    },
    urlType: {<!-- -->
      type: String,
      default: ''
    },
    newlineTag: {<!-- -->
      type: String,
      default: 'p'
    },
    pasteType: {<!-- -->
      type: Number,
      default: 2
    },
    dialogAlignType: {<!-- -->
      type: String,
      default: 'page'
    },
    shadowMode: {<!-- -->
      type: Boolean,
      default: true
    },
    zIndex: {<!-- -->
      type: Number,
      default: 811213
    },
    useContextmenu: {<!-- -->
      type: Boolean,
      default: true
    },
    syncType: {<!-- -->
      type: String,
      default: 'form'
    },
    indentChar: {<!-- -->
      type: String,
      default: '\t'
    },
    cssPath: {<!-- -->
      type: [String, Array]
    },
    cssData: {<!-- -->
      type: String
    },
    bodyClass: {<!-- -->
      type: String,
      default: 'ke-content'
    },
    colorTable: {<!-- -->
      type: Array
    },
    afterCreate: {<!-- -->
      type: Function
    },
    afterChange: {<!-- -->
      type: Function
    },
    afterTab: {<!-- -->
      type: Function
    },
    afterFocus: {<!-- -->
      type: Function
    },
    afterBlur: {<!-- -->
      type: Function
    },
    afterUpload: {<!-- -->
      type: Function
    },
    uploadJson: {<!-- -->
      type: String
    },
    fileManagerJson: {<!-- -->
      type: Function
    },
    allowPreviewEmoticons: {<!-- -->
      type: Boolean,
      default: true
    },
    allowImageUpload: {<!-- -->
      type: Boolean,
      default: true
    },
    allowFlashUpload: {<!-- -->
      type: Boolean,
      default: true
    },
    allowMediaUpload: {<!-- -->
      type: Boolean,
      default: true
    },
    allowFileUpload: {<!-- -->
      type: Boolean,
      default: true
    },
    allowFileManager: {<!-- -->
      type: Boolean,
      default: false
    },
    fontSizeTable: {<!-- -->
      type: Array,
      default: function () {<!-- -->
        return ['9px', '10px', '12px', '14px', '16px', '18px', '24px', '32px']
      }
    },
    imageTabIndex: {<!-- -->
      type: Number,
      default: 0
    },
    formatUploadUrl: {<!-- -->
      type: Boolean,
      default: true
    },
    fullscreenShortcut: {<!-- -->
      type: Boolean,
      default: false
    },
    extraFileUploadParams: {<!-- -->
      type: Array,
      default: function () {<!-- -->
        return []
      }
    },
    filePostName: {<!-- -->
      type: String,
      default: 'imgFile'
    },
    fillDescAfterUploadImage: {<!-- -->
      type: Boolean,
      default: false
    },
    afterSelectFile: {<!-- -->
      type: Function
    },
    pagebreakHtml: {<!-- -->
      type: String,
      default: '<hr style=”page-break-after: always;” class=”ke-pagebreak” />'
    },
    allowImageRemote: {<!-- -->
      type: Boolean,
      default: true
    },
    autoHeightMode: {<!-- -->
      type: Boolean,
      default: false
    },
    fixToolBar: {<!-- -->
      type: Boolean,
      default: false
    },
    tabIndex: {<!-- -->
      type: Number
    }
  },
  setup(props, {<!-- --> emit }) {<!-- -->
    const state = reactive({<!-- -->
      editor: {<!-- -->} as any,
      outContent: props.modelValue
    })
    console.log('state_state', state)
    watch(() => props.modelValue, (val: any) => {<!-- -->
      state.editor & amp; & amp; val !== state.outContent & amp; & amp; state.editor.html(val)
    })
    watch(() => state.outContent, (val: any) => {<!-- -->
      emit('update:modelValue', val)
    })
    onMounted(async() => {<!-- -->
      state.editor = (window as any).KindEditor.create('#' + props.id, {<!-- -->
        width: props.width,
        height: props.height,
        minWidth: props.minWidth,
        minHeight: props.minHeight,
        items: props.items,
        noDisableItems: props.noDisableItems,
        filterMode: props.filterMode,
        htmlTags: props.htmlTags,
        wellFormatMode: props.wellFormatMode,
        resizeType: props.resizeType,
        themeType: props.themeType,
        langType: props.langType,
        designMode: props.designMode,
        fullscreenMode: props.fullscreenMode,
        basePath: props.basePath,
        themesPath: props.cssPath,
        pluginsPath: props.pluginsPath,
        langPath: props.langPath,
        minChangeSize: props.minChangeSize,
        loadStyleMode: props.loadStyleMode,
        urlType: props.urlType,
        newlineTag: props.newlineTag,
        pasteType: props.pasteType,
        dialogAlignType: props.dialogAlignType,
        shadowMode: props.shadowMode,
        zIndex: props.zIndex,
        useContextmenu: props.useContextmenu,
        syncType: props.syncType,
        indentChar: props.indentChar,
        cssPath: props.cssPath,
        cssData: props.cssData,
        bodyClass: props.bodyClass,
        colorTable: props.colorTable,
        afterCreate: props.afterCreate,
        afterChange: function () {<!-- -->
          props.afterChange
          state.outContent = this.html()
        },
        afterTab: props.afterTab,
        afterFocus: props.afterFocus,
        afterBlur: props.afterBlur,
        afterUpload: props.afterUpload,
        uploadJson: props.uploadJson,
        fileManagerJson: props.fileManagerJson,
        allowPreviewEmoticons: props.allowPreviewEmoticons,
        allowImageUpload: props.allowImageUpload,
        allowFlashUpload: props.allowFlashUpload,
        allowMediaUpload: props.allowMediaUpload,
        allowFileUpload: props.allowFileUpload,
        allowFileManager: props.allowFileManager,
        fontSizeTable: props.fontSizeTable,
        imageTabIndex: props.imageTabIndex,
        formatUploadUrl: props.formatUploadUrl,
        fullscreenShortcut: props.fullscreenShortcut,
        extraFileUploadParams: props.extraFileUploadParams,
        filePostName: props.filePostName,
        fillDescAfterUploadImage: props.fillDescAfterUploadImage,
        afterSelectFile: props.afterSelectFile,
        pagebreakHtml: props.pagebreakHtml,
        allowImageRemote: props.allowImageRemote,
        autoHeightMode: props.autoHeightMode,
        fixToolBar: props.fixToolBar,
        tabIndex: props.tabIndex
      })
    })
    return {<!-- -->
      state

    }
  }

})
</script>
  
  <style>
</style>
  • use
<KindEditor id="KindEditor012" />
import KindEditor from '@/component/kind-editor/index.vue'
export default defineComponent({<!-- -->
  components: {<!-- -->
    KindEditor
  },
  setup() {<!-- -->
  return {<!-- -->
  \t\t
  }
  }
  • Effect