tinymce-vue自定义图片上传插件,且在插件中调用vue组件

最近工作项目需要基于tinymce-vue进行插件开发,需要自己写一个插入图片/视频/链接的插件,虽然说tinymce自带就有这些插件,但是这些插件的UI界面长得不是很美观,所以大佬说要自定义tinymce的这些插件。现在就基于tinymce-vue自定义图片上传的插件,来记录一下吧。
先讲一个这个关于图片上传的需求:

  1. 在点击菜单栏的插入图片,要弹出一个我们自定义的vue组件
  2. 点击图片上传后要将图片插入到编辑框里与封面图中
  3. 插入的图片,不管是在编辑框里还是在封面图里,图片的右下角要带着一个裁剪的按钮,让用户可以对图片进行裁剪
    以下是我自己画的一张图

在这里插入图片描述
这里就简单地记录一下吧,然后写一个超简的demo,demo仅记录自定义图片上传插件,且在插件中调用vue组件,并将上传的图片插入到编辑框,就是一个超简单的模板。其他的像上传后再把图片插入后封面图跟图片编辑按钮就不做记录,需要自己拓展

如何引入tinymce-vue插件与汉化插件就不讲了。(demo地址

先在node_modules的tinymce文件夹下的plugins,下创建自定义的插件文件夹例如uploadImg,然后在该文件夹下创建index.js、plugin.js(最好将plugins文件夹移到node_modules外的其他目录,不然每次npm install 插件就都没了,每次都要给插件作备份)

import 'tinymce/plugins/uploadImg';  //这里需要将插件引入
//  然后再init中使用该插件
 plugins: ' uploadImg', // 插件
 toolbar: 'undo redo | uploadImg ', // 顶部排版

自定义插件(就是上面创建的plugin.js)
一开始是想怎么在外部给这个插件传参,但是发现好像不太可行,然后就改成直接在插件里创建组件了。
在插件中调用一个vue的插件,是通过Vue的render函数来做渲染的,一开始是用extend来创建组件,但是效果不好就给换成render了,然后通过组件里抛出的事件来做组件响应,从而来控制我们动态组件。

import Vue from 'vue'
import TinymceUpload from '@/components/Tinymce/TinymceUpload'  // 引入自己的自定义插件
(function () {
  'use strict';

  var global = tinymce.util.Tools.resolve('tinymce.PluginManager');
  var register = function (editor) {
    editor.addCommand('beHeader', function () {});
  };
  var Commands = {
    register: register
  };

  var register$1 = function (editor) {
    // 内有行级元素 需要加上font-size:0   由于部分按钮icon需要自定义,所以这里也定义了一个按钮icon
    editor.ui.registry.addIcon('upload', '<div class="iconBox" style="font-size:0" ><img class=editIcon src="http://placehold.it/24x24" /></div>');
    editor.ui.registry.addButton('uploadImg', {
      icon: 'upload',
      tooltip: 'uploadImg', // 鼠标移到按钮上显示的文字提示
      onAction: function () {
        uploadEvent(editor)
      }
    });
    editor.ui.registry.addMenuItem('uploadImg', {
      icon: 'upload',
      text: 'uploadImg',
      onAction: function () {
        uploadEvent(editor)
      }
    });
  };
  var Buttons = {
    register: register$1
  };
  // 图片按钮事件
  let uploadEvent = function (editor) {
      let loader = new Vue({
        render:(h,con)=> {
          return h(TinymceUpload, {
            props: {
              panelShow: true,
            },
            on: {
              hidePanel(val) { //关闭上传工具弹框
                document.body.removeChild(content.$el)
                content = null
                loader.$destroy()
              },
              successUpload(imgList) { //获得上传完成回调
                imgList.forEach((item, key) => {
                  if (item != undefined) {
                    editor.focus();
                    let idName = `${new Date().getTime()}-${key}` // 给每个图片都加上一个id 时间戳加索引保证图片id唯一 加上id是为了方便后面操作,例如给插入的图片加上编辑按钮
                    editor.selection.setContent(editor.dom.createHTML('img', {
                      src: item,
                      id: idName
                    }));
                  }
                })
              },
            }
          })
        }
      })

    let content = loader.$mount()
    document.body.appendChild(content.$el)
  }
  function Plugin() {
    global.add('uploadImg', function (editor) {
      Commands.register(editor);
      Buttons.register(editor);
    });
  }
  Plugin();

}());

由于这种写法虽然说能够满足我们的业务需求,但我总觉得不太优雅,如果看到篇文章的有缘人有其他好的解决方案也可以一起来交流交流。
虽然看起来挺简单的,但是这只是一个模板,除非只是单纯的插入图片到编辑框,如果加上业务逻辑的话那就没那么简单了。
废话讲完,附上超简版的demo
,后面如果有时间我会结合一些业务需求对插件跟组件进行封装,做成一个组件库,然后以后如果有对tinymce进行插件拓展也会在这个简易版的demo上继续添加定义插件模板

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章