前言
最近因为公司项目的后台管理端需要实现编辑器功能, 一方面满足编辑各类文章内容需求,另一方面要自己编辑一些课程相关的介绍,于是就花了一些时间对比体验现有的一些开源的编辑器。
编辑器之间的简单比较
-
UEditor:基本满足各种需求,依赖于
jquery
但是已经不再维护了,实现上传图片等需要修改源码,界面不太美观,对于老浏览器兼容还不错,但是我这里采用的是VueJS
来开发,所以放弃 -
wangEditor:比较轻量级,最最最重要的是有中文文档上手快,UI也比较漂亮,而且还是国产的, 对于编辑器功能需求少的兄die可以考虑,但是考虑到我这项目业务比较重,所以只好放弃
-
Bootstrap-wysiwyg:简洁好看,依赖于
Bootstrap, jquery
,选择的Element-ui
弃之 -
TinyMCE: 支持图片在线处理,插件多,功能强。 嗯,就选它啦(虽然文档是英文,但是谷歌翻译也不错 ☚)
我们项目要解决的需求说复杂也不复杂,但是却很烦人, 比如:
实现图片上传(基础功能)
模拟手机预览功能(基础功能)
编辑的内容在app中显示要适配
从135编辑器, 秀米等等编辑器拷贝过来的内容要正常显示并且排版还要保持,还要将这些第三方图片上传到自己服务(怕第三方下架图片)
引入并初始化
- 引入tinymace文件
项目采用vue-cli@3.x构建的, 将TinyMCE下载放在index.html同级目录下, 并在index.html
中引入TinyMCE
<script src=./tinymce4.7.5/tinymce.min.js></script>
- 初始化
引入文件后,在html元素上初始化TinyMCE, 由于TinyMCE允许通过CSS选择器来标识可替换的元素,所以我们只需要将包含选择器的对象传递给TinyMCE.init(),代码如下:
<template>
<div class="tinymce-container editor-container">
<textarea :id="tinymceId" class="tinymce-textarea" />
</div>
</template>
<script>
export default {
name: 'Tinymce',
data() {
return {
tinymceId: this.id
}
},
mounted(){
this.initTinymce()
},
methods: {
initTinymce() {
window.tinymce.init({
selector: `#${this.tinymceId}`
})
}
}}
</script>
这样就将textarea
替换为TinyMCE编辑器实例, 做完了最简单的初始化。
配置项
接下来就是添加配置项, 让TinyMCE编辑器功能丰富起来
- 基础配置
关于基础配置, 我就不一一介绍,文档中都有详细的说明,如果英语和我一样弱鸡,可以借助chrome的翻译,大概能看明白。
下面是封装的组件的script
内容, 关于一些配置直接在代码中说明:
import plugins from '@/components/Tinymce/plugins'
import toolbar from '@/components/Tinymce/toolbar'
import {
uploadFile
} from '@/api/file/upload'
export default {
name: 'Tinymce',
props: {
tid: {
type: String,
default: 'my-tinymce-' + new Date().getTime() + parseInt(Math.random(100))
},
content: {
type: String,
default: ''
},
menubar: { // 菜单栏
type: String,
default: 'file edit insert view format table'
},
toolbar: { // 工具栏
type: Array,
required: false,
default () {
return []
}
},
height: {
type: Number,
required: false,
default: 360
}
},
data() {
return {
tinymceId: this.tid,
finishInit: false,
hasChanged: false,
config: {}
}
},
mounted() {
this.initTinymce()
},
methods: {
initTinymce() {
window.tinymce.init({
selector: `#${this.tinymceId}`,
...this.config,
content_style: 'img {max-width:100% !important }', // 初始化赋值
init_instance_callback: editor => {
if (this.content) {
editor.setContent(this.content)
}
this.finishInit = true
editor.on('NodeChange Change SetContent KeyUp', () => {
this.hasChanged = true
})
}, // 上传图片
images_upload_handler: (blobInfo, success, failure) => {
const formData = new FormData();
formData.append('file', blobInfo.blob());
uploadFile(formData).then(res => {
if (res.data.code == 0) {
let file = res.data.data;
success(file.filePath);
return