tinymce + vue3.0

安装相关依赖

  • yarn add tinymce
  • yarn add @tinymce/tinymce-vue

复制依赖包

在vue3的项目 目录的 public 里新建 tinymce文件夹,把node_modules里的skins文件复制到 tinymce文件夹里

下载语言包

在这里插入图片描述

封装组件

<template>
  <div class="tinymce-editor">
    <textarea :id="tinymceId" class="tinymce-textarea" :placeholder="placeholder" />
  </div>
</template>

<script lang='ts'>
import tinymce from 'tinymce/tinymce'
import 'tinymce/themes/silver'
import 'tinymce/plugins/image' // 插入上传图片插件
import 'tinymce/plugins/media' // 插入视频插件
import 'tinymce/plugins/table' // 插入表格插件
import 'tinymce/plugins/lists' // 列表插件
import 'tinymce/plugins/wordcount' // 字数统计插件
import 'tinymce/icons/default'
import { getToken } from '@/utils/auth'
import axios from 'axios'
import { ElMessage } from 'element-plus'

import {
  defineComponent,
  nextTick,
  onMounted,
  reactive,
  toRefs,
  watch
} from 'vue'
import { useStore } from 'vuex'
export default defineComponent({
  name: 'Tinymce',
  props: {
    disabled: {
      type: Boolean,
      default: false
    },
    plugins: {
      type: [String],
      default: 'lists image  table wordcount'
    },
    value: {
      type: String,
      default: ''
    },
    height: {
      type: [Number, String],
      required: false,
      default: 360
    },
    width: {
      type: [Number, String],
      required: false,
      default: '100%'
    },
    type: {
      type: [String],
      default: 'img'
    },
    placeholder: {
      type: [String],
      default: ''
    },
    uid: {
      type: String,
      default: ''
    },
    toolbar1: {
      type: [String],
      default:
        'undo redo | fontsizeselect | fontselect | formatselect | removeformat | bold italic forecolor backcolor | alignleft aligncenter alignright alignjustify | lists image  table | bullist numlist outdent indent'
    },

  },
  setup(props, context) {
    const store = useStore()
    const state: any = reactive({
      tinymceId:
        props.uid + 'tinymce-deitor-' + new Date().getTime().toString(),
      hasChange: false,
      hasInit: false,
      axiosBaseUrl: store.getters.axiosBaseUrl
    })
    watch(
      () => props.value,
      (newVal, oldVal) => {
        if (!state.hasChange && state.hasInit) {
          nextTick(() => {
            ;(window as any).tinymce
              .get(state.tinymceId)
              .setContent(newVal || '')
          })
        }
      }
    )
    const destroyTinymce = () => {
      const tinymce = (window as any).tinymce.get(state.tinymceId)
      if (tinymce) {
        tinymce.destroy()
        tinymce.remove()
      }
    }
    const setContent = (value: any) => {
      if ((window as any).tinymce) {
        ;(window as any).tinymce.get(state.tinymceId).setContent(value)
      }
    }
    const getContent = () => {
      ;(window as any).tinymce.get(state.tinymceId).getContent()
    }
    const imageSuccessCBK = (arr: any) => {
      arr.forEach((v: any) => {
        ;(window as any).tinymce
          .get(state.tinymceId)
          .insertContent(`<img class="wscnph" src="${v.url}" >`)
      })
    }
    const clickTinymceEditor = () => {
      alert('1')
      context.emit('clickTinymceEditor')
    }
    onMounted(() => {
      tinymce.init({
        selector: '#' + state.tinymceId,
        language_url: '/tinymce/langs/zh-Hans.js', // 语言包的路径
        language: 'zh-Hans', //语言
        skin_url: '/tinymce/skins/ui/oxide', // skin路径
        height: props.height, //编辑器高度
        width: props.width,
        branding: false, //是否禁用“Powered by TinyMCE”
        menubar: false, //顶部菜单栏显示
        plugins: props.plugins,
        toolbar1: props.toolbar1,
        // toolbar2: props.toolbar2,
        resize: false,
        paste_data_images: true,
        init_instance_callback: (editor) => {
          if (props.value) {
            editor.setContent(props.value)
          }
          state.hasInit = true
          editor.on('NodeChange Change KeyUp SetContent', () => {
            state.hasChange = true
            context.emit('input', editor.getContent())
          })
          editor.on('click', () => {
            context.emit('clickTinymceEditor')
          })
        },
        setup(editor) {
          editor.on('FullscreenStateChanged', (e) => {
            // _this.fullscreen = e.state
          })
        },
        images_upload_handler(blobInfo, success, failure, progress) {
          if (progress) {
            progress(0)
          }
          const token = getToken()
          if (token) {
            const formData = new FormData()
            formData.append('file', blobInfo.blob(), blobInfo.filename())
            formData.append('Type', props.type)
            axios({
              url: state.axiosBaseUrl + '/Common/UploadFile',
              method: 'post',
              headers: { 'Content-Type': 'multipart/form-data', token: token },
              data: formData
            })
              .then((res: any) => {
                if (res.data.code == 200) {
                  success(res.data.data.FileUrl)
                  if (progress) {
                    progress(100)
                  }
                } else {
                  ElMessage({
                    showClose: true,
                    message: `${res.data.msg}`,
                    type: 'error'
                  })
                }
              })
              .catch((err) => {
                failure('出现未知问题,请刷新页面重新上传!')
                console.log(err)
              })
          } else {
            failure('登录失效,请重新登录!')
          }
        }
      })
    })
    return {
      ...toRefs(state),
      setContent,
      clickTinymceEditor
    }
  }
})
</script>
<style lang="scss" scoped>
.tinymce-textarea {
  font-size: 14px;
  & > p {
    text-indent: 2em;
  }
  touch-action: none;
}
</style>

调用

 <tinymce-editor class="setTinymce" ref="tinymceEditor"
  width="800" height="300" :value=info"
  @input="value => { info= value }"></tinymce-editor>
	
	// import TinymceEditor from '@/components/TinymceCom.vue'
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值