编辑器找了好多,包括百度(UEditor)后台(Java后台不支持)受限制,
wangEditor编辑器编辑的文章没有行高,
而且特别紧凑,后来果断选了Tinymce(最后有文件代码)
1、npm安装使用tinymce,以下两个都要安装
npm install tinymce -S
npm install @tinymce/tinymce-vue -S
2、node_modules里面的tinymce/skins包复制,放到根目录/static里面
3、下载中文包
中文包直通车
4、新建一个Vue文件,我叫tinymce-editor.vue(可以理解为工具类),并初始化tinymce,并导入相应的插件(基本的插件都在node_modules/tinymce/plugins里面,像行高这种没有,需要到Tinymce官网里面去下载第三方插件)
4.1导入插件
4.2 引入插件(plugins和toolbar缺一不可,如 表情包emoticons都要添加)
4.3 初始化
5、图片上传
6、调用初始化,可以在生命周期函数mounted方法调用
7、新建一个Vue文件,然后引用该编辑器文件即可,如下是效果图
编辑器源代码:
<template>
<div class="tinymce-editor"><editor v-model="myValue" :init="init" :disabled="disabled" @onClick="onClick" placeholder="请输入要写的内容"></editor></div>
</template>
<script>
import tinymce from 'tinymce/tinymce';
import Editor from '@tinymce/tinymce-vue';
import 'tinymce/icons/default/icons.min.js';
import 'tinymce/themes/silver';
// 编辑器插件plugins
// 更多插件参考:https://www.tiny.cloud/docs/plugins/
import '@/assets/tinymce/plugins/lineheight/plugin'; //设置行高
import '@/assets/tinymce/plugins/placeholders'; //设置placeholder
import '@/assets/tinymce/plugins/indent2em/plugin'; //设置首行缩进
import '@/assets/tinymce/plugins/ax_wordlimit/plugin'; //设置字数限制
import 'tinymce/plugins/lists'; //有序列表、无序列表
//import "tinymce/plugins/template";//模板
import 'tinymce/plugins/image'; // 插入上传图片插件
import 'tinymce/plugins/imagetools';
import 'tinymce/plugins/table'; // 插入表格插件
import 'tinymce/plugins/preview'; // 插入表格插件
import 'tinymce/plugins/lists'; // 列表插件
import 'tinymce/plugins/emoticons'; //表情插件
import 'tinymce/plugins/media'; //媒体插件
import 'tinymce/plugins/link'; //插入链接
import 'tinymce/plugins/fullscreen';
import 'tinymce/plugins/anchor';
// import "tinymce/plugins/autosave"
import 'tinymce/plugins/autoresize'; //内容自适应插件
import eventBus from '@/utils/EventBus.js'; //兄弟组件传值
export default {
components: {
Editor
},
props: {
value: {
type: String,
default: ''
},
// 基本路径,默认为空根目录,如果你的项目发布后的地址为目录形式,
// 即abc.com/tinymce,baseUrl需要配置成tinymce,不然发布后资源会找不到
baseUrl: {
type: String,
default: ''
},
disabled: {
type: Boolean,
default: false
},
plugins: {
type: [String, Array],
default: 'preview lists imagetools emoticons link media fullscreen anchor autoresize code lineheight table image ax_wordlimit indent2em'
},
toolbar: {
type: [String, Array],
default:
'preview|bold italic forecolor backcolor code indent2em lineheight|emoticons | styleselect | image media| bullist numlist | lists | link |table | removeformat|fullscreen'
}
},
data() {
return {
init: {
//打包前
language_url: '/static/tinymce/langs/zh_CN.js',
language: 'zh_CN',
skin_url: '/static/tinymce/skins/ui/oxide',
emoticons_database_url: '/static/tinymce/emojis.js',
content_css: '/static/tinymce/skins/content/default/content.min.css',
//打包后
/* language_url: '/hyw/static/tinymce/langs/zh_CN.js',
language: 'zh_CN',
skin_url: '/hyw/static/tinymce/skins/ui/oxide',
emoticons_database_url: '/hyw/static/tinymce/emojis.js',
content_css: '/hyw/static/tinymce/skins/content/default/content.min.css', */
max_width: 2000,
width: 550,
min_width: 500,
statusbar: false, // 隐藏编辑器底部的状态栏
selector: 'textarea', // change this value according to your HTML
plugins: this.plugins,
min_height: 270,
toolbar: this.toolbar,
paste_data_images: true,
ax_wordlimit_num: 1,
ax_wordlimit_callback: function(editor, txt, num) {
eventBus.$emit('updateNum', txt.length);
},
/* templates: [
{title: 'selcontent', description: 'selcontent', content: '这是模板内容,<b class="selcontent">这里会被替换为选定的内容</b>,这里也是<b class="selcontent">会被替换</b>。'}
], */
branding: false,
menubar: false,
// 此处为图片上传处理函数,这个直接用了base64的图片形式上传图片,
// 如需ajax上传可参考https://www.tiny.cloud/docs/configure/file-image-upload/#images_upload_handler
images_upload_handler: (blobInfo, success, failure) => {
let _this = this;
let fileNew = [];
let fileParam = {};
let file = blobInfo.blob();
fileParam.content = Math.random() * 20 + file.name;
fileParam.file = file;
fileParam.message = '';
fileParam.status = '';
fileNew.push(fileParam);
let param = {};
_this.$post(_this.$api.UpPhotoFile, param, fileNew).then(data => {
if (data.code === _this.$api.SUCCEED) {
let resobj = data.resobj;
let photoArr = resobj.photoFile;
for (var i = 0; i < photoArr.length; i++) {
let photoString = photoArr[i];
success(_this.$DbUtils.getItem(_this.$api.imageUrl) + photoString);
}
} else {
failure(data.errormsg);
}
});
}
},
myValue: this.value
};
},
mounted() {
tinymce.init({});
},
methods: {
// 添加相关的事件,可用的事件参照文档=> https://github.com/tinymce/tinymce-vue => All available events
// 需要什么事件可以自己增加
onClick(e) {
this.$emit('onClick', e, tinymce);
},
// 可以添加一些自己的自定义事件,如清空内容
clear() {
this.myValue = '';
},
onChage(e) {},
async uploadImg(FormData) {
let res = await this.$api2.upload_img(FormData);
}
},
watch: {
value(newValue) {
if (newValue.length > 10) {
this.myValue = newValue.substring(0, 10);
}
this.myValue = newValue;
},
myValue(newValue) {
this.$emit('input', newValue);
}
}
};
</script>
<style scoped></style>
调用编辑器模板
import TinymceEditor from '@/components/tinymce-editor.vue';
<tinymce-editor v-model="msg" :disabled="disabled" ref="editor"></tinymce-editor>