vue3集成tinymce富文本编辑器

vue3集成tinymce富文本编辑器

前言:因为公司要换富文本编辑器,思前想后选择了tinymce,记录一下我的使用方法以及使用时遇到的坑

最终效果图
效果图

正文:

1.安装依赖

npm i @tinymce/tinymce-vue tinymce

这里我选择的是5.0.0的tinymce-vue,5.10.7的tinymce,不建议使用tinymce6的版本

“@tinymce/tinymce-vue”: “^5.0.0”,
“tinymce”: “^5.10.7”,

2.建tinymce文件夹

在这里插入图片描述
在public下建tinymce文件夹,用来存放语言包和皮肤包,官网下载需要的语言包:https://www.tiny.cloud/get-tiny/language-packages/
在node_modules/tinymce/skins,把整个skins文件夹复制过来

3.封装组件TEditor(自己取名)

  • 引入依赖
  import tinymce from 'tinymce/tinymce'
  import Editor from '@tinymce/tinymce-vue'
  import 'tinymce/themes/silver'
  import 'tinymce/icons/default'
  • 配置tinymce初始值
init: {
          height: this.height,
          emoticons_database_url: process.env.BASE_URL + '/tinymce/langs/emojis.js',
          language_url: process.env.BASE_URL + '/tinymce/langs/zh-Hans.js',
          language: 'zh-Hans',
          // 皮肤:这里引入的是public下的资源文件
          skin_url: process.env.BASE_URL + '/tinymce/skins/ui/oxide',
          plugins: this.plugins,
          toolbar: this.toolbar,
          content_css: process.env.BASE_URL + '/tinymce/skins/content/default/content.css',
          branding: false,
          // 隐藏菜单栏
          menubar: false,
          // 是否显示底部状态栏
          statusbar: false,
          // convert_urls: false,
          // 初始化完成
          init_instance_callback: (editor) => {
            console.log('初始化完成:', editor)
          },
          images_upload_handler: (blobInfo, success, failure) => {
              if(blobInfo.blob().size / 1024 / 1024 > 10){
                    failure('上传失败,图片大小请控制在 10M 以内')
              }else{
                const params = new FormData()
                params.append('file', blobInfo.blob())
                axios({
                  url: `${this.app.proxy.$apiConfig.flowbaas}/WF/Ath/AttachmentUploadRichText.do`,
                  method: 'post',
                  data: params,
                  headers: {
                    'Content-Type': 'multipart/form-data'
                  }
                }).then(res => {
                      if(res.data.errno === 0){
                            success(res.data.data.url) //上传成功,在成功函数里填入图片路径
                      }else{
                            failure('上传失败')
                      }
                }).catch(() => {
                      failure('上传出错,服务器开小差了呢')
                })
          }
        }
        },

要注意语言包的路径和皮肤包的路径,我这项目需要加上process.env.BASE_URL,正常情况下可以不加,上传图片的方法images_upload_handler也要根据实际情况修改

  • 完整组件如下
<template>
    <div class='tinymce-box'>
      <editor v-model='textContent' :init='init' :disabled='disabled' @onClick='onClick'></editor>
    </div>
  </template>
  
  <script>
  import { getCurrentInstance } from 'vue'
  import tinymce from 'tinymce/tinymce'
  import Editor from '@tinymce/tinymce-vue'
  import 'tinymce/themes/silver' // 主题文件
  import 'tinymce/icons/default'
  // import 'tinymce/models/dom'
  import 'tinymce/plugins/lists'
  import 'tinymce/plugins/emoticons' 
  import 'tinymce/plugins/link' 
  import 'tinymce/plugins/image' 
  import 'tinymce/plugins/table' 
  import 'tinymce/plugins/code' 
  import 'tinymce/plugins/hr' 
  import 'tinymce/plugins/fullscreen' 
  import axios from 'axios'
  export default {
    name: 'Tinymce',
    components: { Editor },
    props: {
      height: {
        type: String,
        default: '300'
      },
      value: {
        type: String,
        default: ''
      },
      disabled: {
        type: Boolean,
        default: false
      },
      plugins: {
        type: [String, Array],
        default: 'lists emoticons link image table code hr fullscreen'
    },
      toolbar: {
        type: [String, Array],
        // eslint-disable-next-line vue/require-valid-default-prop
        default: ['blockquote | bold underline italic strikethrough superscript subscript removeformat | fontsizeselect fontselect styleselect',
                 'bullist numlist align | emoticons link image table code hr | undo redo | fullscreen']
      }
    },
    data() {
      return {
        app: getCurrentInstance(),
        init: {
          height: this.height,
          emoticons_database_url: process.env.BASE_URL + '/tinymce/langs/emojis.js',
          language_url: process.env.BASE_URL + '/tinymce/langs/zh-Hans.js',
          language: 'zh-Hans',
          // 皮肤:这里引入的是public下的资源文件
          skin_url: process.env.BASE_URL + '/tinymce/skins/ui/oxide',
          
          // skin_url: 'tinymce/skins/ui/oxide-dark',//黑色系
          plugins: this.plugins,
          toolbar: this.toolbar,
          content_css: process.env.BASE_URL + '/tinymce/skins/content/default/content.css',
          branding: false,
          // 隐藏菜单栏
          menubar: false,
          // 是否显示底部状态栏
          statusbar: false,
          // convert_urls: false,
          // 初始化完成
          init_instance_callback: (editor) => {
            console.log('初始化完成:', editor)
          },
          images_upload_handler: (blobInfo, success, failure) => {
              if(blobInfo.blob().size / 1024 / 1024 > 10){
                    failure('上传失败,图片大小请控制在 10M 以内')
              }else{
                const params = new FormData()
                params.append('file', blobInfo.blob())
                axios({
                  url: `${this.app.proxy.$apiConfig.flowbaas}/WF/Ath/AttachmentUploadRichText.do`,
                  method: 'post',
                  data: params,
                  headers: {
                    'Content-Type': 'multipart/form-data'
                  }
                }).then(res => {
                      if(res.data.errno === 0){
                            success(res.data.data.url) //上传成功,在成功函数里填入图片路径
                      }else{
                            failure('上传失败')
                      }
                }).catch(() => {
                      failure('上传出错,服务器开小差了呢')
                })
          }
        }
        },
        textContent: this.value
      }
    },
    watch: {
      value (newValue) {
        console.log(newValue, '1')
        this.textContent = newValue
      },
      textContent (newValue) {
        // 自定义事件给父组件传递数据
        console.log(newValue, '2')
        this.$emit('input', newValue)
      }
    },
    // 实例创建完成
    created() {
    },
    // 组件挂载完毕
    mounted() {
      // 初始化 tinymce
      tinymce.init({})
    },
    methods: {
      onClick (e) {
        // 自定义事件给父组件传递数据
        this.$emit('onClick', e, tinymce)
      },
      // 可以添加一些自己的自定义事件,如清空内容
      clear () {
        this.textContent = ''
      }
    }
  
  }
  </script>
  
  <style scoped>
  .tinymce-box{
    margin: 10px
  }
  </style>

有几个要注意的地方,1、表情功能可能会找不到路径,然后报错,可以把依赖包里的emojis.js复制过来引入emoticons_database_url,在这里插入图片描述
2、toolbar和plugins的配置,这两个按需配置,可以参考这篇文章 toolbar配置
3、图片上传根据实际情况修改接口

4、调用组件

<tinymce :height="300" ref="editor" :value="Value"></tinymce>
import Tinymce from './TEditor.vue'
components: { Tinymce }

我这个是vue3版本的,vue2版本的可能有出入,也大差不差吧

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值