VUE使用tinymce经验

3,588 阅读3分钟

背景

原先用的web编辑器是百度前端团队开发的ueditor,百度前端的开源项目,功能强大,基于jQuery,但是此项目已经很久没有再维护,而且限定了后端代码,修改起来比较费劲,最新一次更新还在2016.05.18,因为已经不再维护了,需要大量修改源码,依赖jquery,修改的内容可能污染全局css。

常见富文本编辑器比较

富文本编辑器 优点 缺点
Tinymce 支持图片在线处理,插件多,功能强,编辑能力优秀,界面好看。文档好,bug少,无外部依赖,用户评价好,更新频率快 低版本IE不兼容
ueditor 插件多,基本满足各种需求,类似贴吧中的回复界面 不再维护,图片只能上传到本地服务器,如果需要上传到其他服务器需要改动源码,较为难办。
wangEditor 轻量、简洁、易用 没有强大的后台,案例不是很多,也不便于定制化开发
bootstrap-wysiwyg 轻量,好看,使用方便 没有开发文档不便于阅读使用,无字体变色,无视频上传功能 。需要一定的浏览器支持,毕竟需要bootstrap。
kindEditor 轻量,好看,使用方便 存在图片上传问题,如果上传历史过多,会全部加载,导致浏览器卡,反应慢,而且好久没见更新了
CKEditor 功能强大配置灵活ui漂亮 需要指定专门的node以及npm版本,兼容性差

最终选择方案

Tinymce

功能强,bug少,无外部依赖,用户评价好,更新频率快。 插件多,tinymce 官方为 vue 项目提供了一个组件 tinymce-vue; 有官方提供的模板选择插件,上传图片插件,字数统计插件,表格插件,添加超链接插件等等我们有可能用到的插件。 是唯一一个从 word 粘贴过来还能保持绝大部分格式的编辑器,可以自己在工具栏加函数方便扩展自用功能。

插件安装

安装tinymce-vue

npm install @tinymce/tinymce-vue -S

下载tinymce

npm install tinymce -S

初始化

引入基本文件
import tinymce from 'tinymce/tinymce'
import Editor from '@tinymce/tinymce-vue'
import 'tinymce/themes/modern/theme'
<editor id="tinymce" v-model="value" :init="init"></editor>
语言包和主题包需要放到项目静态文件夹下
init: {
	language_url: '/static/tinymce/langs/zh_CN.js',//语言包的路径
	language: 'zh_CN',//语言包(需下载)
	skin_url: '/static/tinymce/skins/lightgray',//skin路径
	height: 300,//编辑器高度
	plugins: ......,//插件
	toolbar: ......//工具栏
}
引入插件
import 'tinymce/plugins/image'; // 插入上传图片插件
import 'tinymce/plugins/media';// 插入视频插件
import 'tinymce/plugins/table';// 插入表格插件
import 'tinymce/plugins/lists';// 列表插件
import 'tinymce/plugins/wordcount';// 字数统计插件
import 'tinymce/plugins/template';// 模板插件
import 'tinymce/plugins/lists';// 列表插件
import 'tinymce/plugins/link';// 链接插件
......
工具栏
plugins: 'lists image media table textcolor wordcount contextmenu',
toolbar: 'undo redo |  formatselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | lists image media table | removeformat'
......

上传图片功能

需要写在init函数中

images_upload_url: 'service/common/storage',
images_upload_handler: (blobInfo, success, failure) => {
                    let formData = new FormData();
                    formData.append('file', blobInfo.blob(), blobInfo.filename());
                    oc.ajax.post('/service/common/storage', formData, {contentType: false} ).then(res => {
                        let location=`/service/common/storage?key=${res}`;
                        success(location);
                    }
                    ).catch(error =>{
                        failure(error);
                    });
                    # oc.ajax是用的自己封装的ajax组件,这其实就是post请求
                },

若需要支持粘贴图片直接上传 则在init里加上

paste_data_images: true

仿照图片上传功能写出附件和视频上传功能

文件上传需要插入link插件和加上link工具

file_picker_types: 'image file media',
file_picker_callback: function(callback, value, meta) {
    let input = document.createElement('input');
    input.setAttribute('type', 'file');
    // 你可以给input加accept属性来限制上传的文件类型
    // input.setAttribute('accept', '.jpg,.png');
    input.click();
    input.onchange = function() {
        let file = this.files[0];
        let formData = new FormData();
        formData.append('file', file, file.name);
        oc.ajax.post('/service/common/storage', formData, {contentType: false}).then(res =>{
            let location=`/service/common/storage?key=${res}`;
            # Provide image and alt text for the image dialog
            if (meta.filetype == 'image') {
                callback(location, {alt: 'My image'});
            }
            # Provide file and text for the link dialog
            if (meta.filetype == 'file') {
                callback(location, {text: 'My file'});
            }
            # Provide alternative source and posted for the media dialog
            if (meta.filetype == 'media') {
                callback(location, {title: 'My media'});
            };
        });
    };
}