原先项目使用quill富文本编辑器但是对于文章的样式展现不够好,所以转而使用Toast UI ,Toast UI相对于quill而言多了markdown编辑模式,样式展示丰富了很多,但是缺点就是相关Toast UI的中文文档实在太少,网上基本没有如何自定义Toast UI的按钮功能的中文教程,所以记录此次的爬坑。
首先先把所有功能代码进行展示
<template>
<div>
<editor @input="onContentChange"
ref="tuiEditor"
:value="value"
:mode="mode"
:options="option"
:height="height"
:previewStyle="previewStyle"
@change="onEditorChange" ></editor>
<input class="hidden"
ref="files"
@change="uploadFile"
type="file"
accept="image/*">
<span class="warnTip mt2 block">
提示:超链接请输入完整格式(例如https://xxx.xxx.xxx或者http://xxx.xxx.xxx)
</span>
</div>
</template>
<script lang="ts">
import {Vue, Component, Prop} from 'vue-property-decorator';
import 'tui-editor/dist/tui-editor.css'
import 'tui-editor/dist/tui-editor-contents.css'
import 'codemirror/lib/codemirror.css'
import 'highlight.js/styles/github.css'
import {Editor} from '@toast-ui/vue-editor'
import {option} from '@/components/service-flow/uploadImgByMd'
// interface Uplaod{
// uploadFn:
// }
const defaultOptions = {
minHeight: '200px',
language: 'en_US',
useCommandShortcut: true,
useDefaultHTMLSanitizer: true,
usageStatistics: true,
hideModeSwitch: false,
toolbarItems: [
'heading',
'bold',
'italic',
'strike',
'divider',
'hr',
'quote',
'divider',
'ul',
'ol',
'task',
'indent',
'outdent',
'divider',
'table',
// 'image',
'link',
'divider',
'code',
'codeblock'
]
};
@Component({
components: {
Editor
},
})
export default class ToastEditor extends Vue {
//name
//prop
@Prop()
value!:any;
@Prop({
default:"markdown"
})
mode!:any;
@Prop(
{
default:"vertical"
}
)
previewStyle!:string;
@Prop(
{
default:"450px"
}
)
height!:string;
@Prop({
default(){
return{
uploadFn:option.uploadFn,
successDataTransform:option.successDataTransform,
fail:"",
}
}
})
upload!:any;
@Prop({
default(){
return {
}
}
})
uploadField!:any;
//data
option = defaultOptions;
//computed
//watch
//life cycle
mounted(){
this.setButtonOfImg();
}
//methods
uploadFile(e){
let target = e.target;
let file = target.files[0];
//文件验证
if(!this.fileValid(file)){
target.value="";
return
};
if(typeof this.upload.uploadFn == "function"){
this.uploadField.file = file;
this.upload.uploadFn(this.uploadField).then(res=>{
this.upload.successDataTransform&&this.upload.successDataTransform(res,this.addImgToMd)
})
}
console.log("file",file);
//重置input file值
target.value="";
}
setButtonOfImg(){
let editor = (<any>this.$refs.tuiEditor).invoke('getCurrentModeEditor');
let editorUI = (<any>this.$refs.tuiEditor).invoke('getUI');
let toolbar = editorUI.getToolbar();
let fileDom = this.$refs.files;
editor.eventManager.addEventType('insertImg');
editor.eventManager.listen('insertImg', function() {
(<any>fileDom).click();
});
toolbar.addButton({
name: 'customize',
className: 'toast toast-img-icon',
event: 'insertImg',
tooltip: 'Insert img',
}, 13);
}
//文件验证
fileValid(file){
// console.log("file_valid",file);
if(file.size/1024>this.$bigDateConfig.IMG_SIZE_LIMIT){
this.$message.error(`编辑图片超过${this.$bigDateConfig.IMG_SIZE_LIMIT}kb限制`);
return false;
}
return true;
}
//添加图片到markdown
addImgToMd(data){
let editor = (<any>this.$refs.tuiEditor).invoke("getCodeMirror");
let editorHtml = (<any>this.$refs.tuiEditor).invoke("getCurrentModeEditor");
let isMarkdownMode = (<any>this.$refs.tuiEditor).invoke('isMarkdownMode');
if(isMarkdownMode){
editor.replaceSelection(`![img](${data})`);
}else {
let range = editorHtml.getRange();
let img = document.createElement('img');
img.src=`${data}`;
img.alt="img";
range.insertNode(img);
}
}
onEditorChange(){
}
onContentChange(data){
this.$emit("input",data);
}
}
</script>
<style>
.toast.toast-img-icon{
background-position: -130px -4px;
}
</style>
自定义Toast UI功能主要要解决三个问题
1.如何添加自定义图标到功能栏?
2.如何为添加的自定义图标添加功能?
3.如何将后台传送的图片链接地址插入到编辑器中?
先来解决第一与第二个问题
const defaultOptions = {
minHeight: '200px',
language: 'en_US',
useCommandShortcut: true,
useDefaultHTMLSanitizer: true,
usageStatistics: true,
hideModeSwitch: false,
toolbarItems: [
'heading',
'bold',
'italic',
'strike',
'divider',
'hr',
'quote',
'divider',
'ul',
'ol',
'task',
'indent',
'outdent',
'divider',
'table',
// 'image', //注释掉编辑器自带的上传图片功能
'link',
'divider',
'code',
'codeblock'
]
};
setButtonOfImg(){
//获取编辑器
let editor = (<any>this.$refs.tuiEditor).invoke('getCurrentModeEditor');
let editorUI = (<any>this.$refs.tuiEditor).invoke('getUI');
//获取编辑器上的功能条
let toolbar = editorUI.getToolbar();
let fileDom = this.$refs.files;
editor.eventManager.addEventType('insertImg');
//这个事件监听就是添加自定义功能的地方
editor.eventManager.listen('insertImg', function() {
(<any>fileDom).click();
});
//为功能条添加自定义按钮
toolbar.addButton({
name: 'customize',
className: 'toast toast-img-icon',//自定义按钮的类名
event: 'insertImg',//对应上文的eventManager添加的监听事件类型,通过点击触发
tooltip: 'Insert img',//鼠标hover自定义按钮的提示信息
}, 13);
}
还有一个样式
由于Toast UI自带的功能条的图标是雪碧图,所以我们可以通过background-position使用编辑器自带的插入图片的图标
<style>
.toast.toast-img-icon{
background-position: -130px -4px;
}
</style>
基本上通过上述代码就可以解决问题已与问题二
现在来解决如何将后台传送的图片链接地址插入到编辑器中
//添加图片到markdown
addImgToMd(data){
let editor = (<any>this.$refs.tuiEditor).invoke("getCodeMirror");
let editorHtml = (<any>this.$refs.tuiEditor).invoke("getCurrentModeEditor");
let isMarkdownMode = (<any>this.$refs.tuiEditor).invoke('isMarkdownMode');
//确认当前是富文本还是markdown编辑器 两种的实现方式不同
if(isMarkdownMode){
//通过替换markdown内容来添加图片
editor.replaceSelection(`![img](${data})`);
}else {
let range = editorHtml.getRange();
let img = document.createElement('img');
img.src=`${data}`;
img.alt="img";
//通过添加dom元素来添加图片
range.insertNode(img);
}
}
全文结束