最近工作項目需要基於tinymce-vue進行插件開發,需要自己寫一個插入圖片/視頻/鏈接的插件,雖然說tinymce自帶就有這些插件,但是這些插件的UI界面長得不是很美觀,所以大佬說要自定義tinymce的這些插件。現在就基於tinymce-vue自定義圖片上傳的插件,來記錄一下吧。
先講一個這個關於圖片上傳的需求:
- 在點擊菜單欄的插入圖片,要彈出一個我們自定義的vue組件
- 點擊圖片上傳後要將圖片插入到編輯框裏與封面圖中
- 插入的圖片,不管是在編輯框裏還是在封面圖裏,圖片的右下角要帶着一個裁剪的按鈕,讓用戶可以對圖片進行裁剪
以下是我自己畫的一張圖
這裏就簡單地記錄一下吧,然後寫一個超簡的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上繼續添加定義插件模板