vue使用tinymce富文本框

450 阅读1分钟
tinymce富文本是一个轻量级插件,内置的功能比较齐全。

中文文档:tinymce.ax-z.cn/ 下面主要记录我根据项目需要在vue项目中封装富文本编辑器组件。

  • 下载插件
npm install @tinymce/tinymce-vue
  • 新建一个组件,封装tinymce作为通用组件
<template>
  <div
    class="tinymce-editor"
    id="tinymce-editor"
  >
    <editor
      :style="disabled === false ? 'min-height:70px' : 'min-height:0px'"
      v-model="tempValue"
      :init="init"
      :disabled="disabled"
    ></editor>
  </div>
</template>
<script>
import tinymce from "tinymce/tinymce";
import Editor from "@tinymce/tinymce-vue";
import "tinymce/themes/silver/theme"; // 引用主题文件
import "tinymce/icons/default"; // 引用图标文件
import "tinymce/plugins/quickbars"; //快捷菜单
import "tinymce/plugins/textcolor";
import "tinymce/plugins/paste"
import "tinymce/plugins/image"; //图片
import "tinymce/plugins/imagetools"; //图片工具
import "tinymce/plugins/importcss"; //图片工具
import "tinymce/plugins/fullscreen"; //全屏
import "tinymce/plugins/lists";//列表
import "tinymce/plugins/link";//链接
import { getToken } from "@/utils/auth";
import axios from 'axios'
export default {
  components: {
    Editor
  },
  props: {
  //富文本框值
    value: {
      type: String,
      default: null
    },
    //是否可编辑
    disabled: {
      type: Boolean,
      default: false
    },
  },
  data () {
    return {
      init: {
        selector: `#tinymce-editor`,
        //占位字符,此属性不知道为什么不起作用
        placeholder: '请再次输入内容',
        language_url: require('../../assets/tinymce/zh_CN'), //如果语言包不存在,指定一个语言包路径
        language: "zh_CN", //语言
        skin_url: require('tinymce/skins/ui/oxide/skin.css'), //如果主题不存在,指定一个主题路径,
        menubar: false, // 隐藏菜单栏
        height: '300px',
        plugins:
          "quickbars paste imagetools image fullscreen lists link", // 插件需要import进来
        paste_as_text: 'false',
        //复制图片
        paste_data_images: true,
        toolbar: [ //数组写法
          'fontsizeselect h1 | bold backcolor italic  strikethrough  underline  forecolor fullscreen bullist numlist'
        ],
        fontsize_formats: '11px 12px 14px 16px 18px 24px 36px 48px',
        quickbars_insert_toolbar: false,
        custom_colors: false,
        quickbars_selection_toolbar: 'bold  |  forecolor',
        content_style: 'p {white-space:pre-line;margin: 5px 0; font-size: 14px;color:#303133}',
        contextmenu: '',
        branding: false,
        visual: true,
        elementpath: false,
        resize: false, // 禁止改变大小
        statusbar: false, // 隐藏底部状态栏
        startContent: '',//初始内容
        image_uploadtab: 'false',
       //图片上传
        images_upload_handler: (blobInfo, success, failure) => {
          this.handleImgUpload(blobInfo, success, failure);
        }
      },
      tempValue: this.value
    };
  },
  mounted () {
    tinymce.init({});
  },
  methods: {
  //图片上传函数
    handleImgUpload (blobInfo, success, failure) {
      const formdate = new FormData();
      formdate.append("file", blobInfo.blob()); //imageFile文件名和后端统一
      axios({
        url: process.env.NODE_ENV === 'development' ? '/api/common/upload' : '/common/upload',
        method: "post",
        data: formdate,
        headers: {
          "Content-Type": "multipart/form-data",
          Authorization: "Bearer " + getToken(),
        },
      }).then(response => {
        console.log("response", response.data);
        if (response.data.code == 200) {
          success(response.data.url); //回显url
        } else {
          failure(response.data.msg);
          this.$message.error(response.data.msg);
        }
      });
    }
  },
  watch: {
    value (newValue) {
      this.tempValue = newValue;
    },
    tempValue (newValue) {
      this.$emit("input", newValue);
    },

  }
};
</script>
<style lang="scss" >
.tox-tinymce-aux {
  z-index: 9999 !important;
}
.mce-content-body p img {
  max-width: 80% !important;
  width: auto !important;
  height: auto !important;
}
</style>
  • 在组件中调用 此处需要使用v-if控制是否显示,避免绑定的属性值不准确,使用在对话弹框中可以赋值v-if和控制弹框显示的值同步,保证每次打开获取到的都是最新赋值的数据
 <Editor  v-model:value="formData.errorInfo" v-if="visible" @input="inputContent"></Editor>