Vue中使用tinymce富文本编辑器

效果
Vue中使用tinymce富文本编辑器
“@tinymce/tinymce-vue”: “^3.2.3”,
“tinymce”: “^5.5.0”,

一、安装

npm install tinymce -S

npm install @tinymce/tinymce-vue -S

二、下载资源

将下面两个资源下载下载,放到资源文件里面。下载tinymce文件的目的是解决加载缓慢,白屏问题

中文包下载地址

Vue中使用tinymce富文本编辑器
tinymce资源文件下载地址
根据相应的版本下载
Vue中使用tinymce富文本编辑器

三、创建组件开始使用

  • 1、解决加载缓慢,白屏问题
    把上面下载的tinymce文件放在资源文件后,需要在index.html中引入使用tinymce.min.js
<script src="/static/tinymce/tinymce.min.js"></script>
  • 2、组件完整代码

    html

    <editor :init="editorInit" v-model="contentHtml" :disabled="disabled" :autoresize="autoresize" />
    <!-- 上传视频没有一个正在上传的遮罩,那么就需要自己写一个遮罩,就如下面的div,我这里只做展示,样式没有写 -->
    <div v-if="loading" />

js

import Editor from "@tinymce/tinymce-vue";
  // import 'tinymce/plugins/media'
  // 后端上传接口,按照需求而定
  import {
    upload,
  } from "../api/api";
  import request from "../api/request";
  import store from '../store/index'
  import util from '../Util'
var util={}
  export default {
    name: "TinyMceEditor",
    model: {
      prop: "content",
      event: "change",
    },
    props: {
      // 绑定的文本内容
      content: {
        type: String,
        default: "",
      },
      // 是否禁止输入
      disabled: {
        type: Boolean,
        default: false,
      },
      // true则自适应高
      autoresize: {
        type: Boolean,
        default: false,
      },
    },
    components: {
      Editor,
    },

    data: () => ({
      // 编辑器配置
      editorInit: {
        language_url: "/static/zh_CN.js", //汉化文件的路径, 这里的原始路径是'/public/zh_CN.js'
        language: "zh_CN",

        height: 500,
        menubar: true,
        plugins: [
          "advlist autolink lists link image charmap print preview anchor",
          "searchreplace visualblocks code fullscreen",
          "insertdatetime media table paste code help wordcount",
          "image media",
        ],
        toolbar: "undo redo | formatselect | bold italic underline strikethrough superscript subscript codeformat forecolor backcolor removeformat| \
           alignleft aligncenter alignright alignjustify  outdent indent lineheight| \
           bullist numlist  | link image media template codesample inserttable table    | \
           charmap emoticons hr insertdatetime | cut copy newdocument print | \
           spellchecker |searchreplace preview fullscreen | help | ",
        file_picker_types: ' media',
        content_css: 'css/content.css',
        // 自定义视频上传
        file_picker_callback: function (cb, value, meta) {
          if (meta.filetype == 'media') {
            //创建一个隐藏的type=file的文件选择input
            let input = document.createElement('input');
            input.setAttribute('type', 'file');
            input.onchange = function (e) {
              let file = e.target.files[0]; //只选取第一个文件。如果要选取全部,后面注意做修改
              store.commit('setParam', {
                loading: true
              })
              const formData = new FormData();
              formData.append("file", file);
              request(upload, formData)
                .then((res) => {
                  store.commit('setParam', {
                    loading: false
                  })
                  if (res.code === 0) {
                    let fileUrl = res.data.url;
                    cb(fileUrl, {
                      title: file.name
                    });
                    return;
                  }
                  util.message("err", "上传失败")
                })
                .catch(() => {
                  store.commit('setParam', {
                    loading: false
                  })
                  util.message("err", "上传失败")
                });
            }
            //触发点击
            input.click();

          }
        },
        //自定义逻辑替换 Tinymce 的默认媒体嵌入逻辑 --处理添加视频显示问题
        media_url_resolver: function (data, resolve) {
          try {
            let videoUri = encodeURI(data.url);
            let embedHtml
            if (videoUri) {
              embedHtml = `<p>
                    <span
                        class="mce-object mce-object-video"
                        data-mce-selected="1"
                        data-mce-object="video"
                        data-mce-p-width="100%"
                        data-mce-p-height="auto"
                        data-mce-p-controls="controls"
                        data-mce-p-controlslist="nodownload"
                        data-mce-p-allowfullscreen="true"
                        data-mce-p-src=${videoUri} >
                        <video src=${data.url} width="100%" height="auto" controls="controls" controlslist="nodownload">
                        </video>
                    </span>
                </p>
                <p style="text-align: left;"></p>`;
            } else {
              embedHtml = ""
            }
            resolve({
              html: embedHtml
            });
          } catch (e) {
            resolve({
              html: ""
            });
          }
        },

        branding: false,

        // 自定义图片上传
        images_upload_handler: (blobInfo, success, failure) => {
          const formData = new FormData();
          formData.append("file", blobInfo.blob());
          request(upload, formData)
            .then((res) => {
              if (res.code === 0) {
                let file = res.data.url;
                success(file);
                return;
              }
              failure("上传失败");
            })
            .catch(() => {
              failure("上传出错");
            });
        },

      },

      contentHtml: "",
      updateTimer: null, //防抖
    }),
    computed: {
      loading() {
        return store.state.loading
      }
    },
    watch: {
      content(valueFromParent) {
        // 由父组件自动修改的内容,同步到子组件
        if (valueFromParent !== this.contentHtml) {
          this.contentHtml = valueFromParent;
        }
      },

      contentHtml(valueFromChild = "") {
        // 向父组件派发change事件
        if (valueFromChild !== this.content) {
          this.$emit("change", valueFromChild);
        }
      },
    },
    created() {
      store.commit('setParam', {
        loading: false
      })
    },
    beforeDestroy() {
      this.updateTimer && clearTimeout(this.updateTimer);
    },
  };

pluginstoolbar是成对存在的,plugins必不可少,

Vue中使用tinymce富文本编辑器
toolbar是页面中操作栏导航的排列Vue中使用tinymce富文本编辑器

四、一些需求实现

1、在光标处插入内容

在光标处插入内容,此方法会有插入后立即删除却删不掉的问题

 tinyMCE.activeEditor.selection.setContent(`<span style="color:red">{total_score}</span>`)

在光标处插入内容,这个比较完美

tinyMCE.activeEditor.execCommand('mceInsertContent',false,`<span style="color:red">{total_score}</span>`);

2、获取内容、设置内容

  • 如果当前页面只有一个编辑器
tinyMCE.activeEditor.getContent() //获取内容

tinyMCE.activeEditor.setContent('需要设置的编辑器内容') //设置内容
  • 如果当前页面有多个编辑器
tinyMCE.editors[0].getContent() //获取第一个编辑器的内容

tinyMCE.editors[0].setContent('需要设置的编辑器内容') //设置第一个编辑器的内容
  • 获取不带HTML标记的纯文本内容
    取到的 text 即为纯文本内容
 var activeEditor = tinymce.activeEditor;
 var editBody = activeEditor.getBody();
 activeEditor.selection.select(editBody);
 var text = activeEditor.selection.getContent({'format': 'text'});
上一篇:响应式布局


下一篇:IjkMediaPlayer的mNativeMediaPlayer的设置