上周组内讨论富文本编辑器的事,说VueQuillEditor虽然能实现功能,但是效果上要比tinymce差一些,
原来系统里引用过一版tinymce,说用tinymce来替换一下富文本组件,于是我查看了一下系统中的tinymce,发现他是直接用了个html承载,挂到textarea上了。如下:
html挂载了tinymce.min.js
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>文本编辑器</title>
<style>
html, body{
margin: 0;
padding: 0;
height: 100%;
}
</style>
<script src="<%= BASE_URL %>tinymce/tinymce.min.js"></script>
</head>
<body>
<textarea id="container" style="width:100%;height:100%;"></textarea>
</body>
</html>
主main.js 直接使用init生成tinymce界面
/* global: tinymce */
import axios from 'axios';
const { VUE_APP_OUTTER } = process.env;
tinymce.init({
selector: '#container',
language: 'zh_CN',
images_upload_url: '/api/travel-service/travel/queryservice/article/photo',
plugins:
'print preview searchreplace autolink directionality visualblocks visualchars fullscreen image link media codesample table charmap hr pagebreak nonbreaking anchor toc insertdatetime advlist lists imagetools textpattern help powerpaste',
toolbar:
'formatselect | bold italic strikethrough forecolor backcolor | link image | alignleft aligncenter alignright alignjustify | numlist bullist outdent indent | removeformat',
powerpaste_word_import: 'propmt', // 参数可以是propmt, merge, clear,效果自行切换对比
powerpaste_html_import: 'propmt', // propmt, merge, clear
powerpaste_allow_local_images: true,
paste_data_images: true,
// image_prepend_url: `${VUE_APP_OUTTER}`,
images_upload_handler(blobInfo, success, failure) {
const url = '/api/travel-service/travel/queryservice/article/photo';
const formData = new FormData();
formData.append('photo', blobInfo.blob(), blobInfo.filename());
axios.post(url, formData).then((response) => {
if (response.data.state === 'SUCCESS') {
success(`${VUE_APP_OUTTER}${response.data.url}`);
} else {
failure();
}
});
},
init_instance_callback(editor) {
editor.on('Change', () => {
const content = tinymce.activeEditor.getContent();
window.parent.postMessage(`__CONTENT_CHANGE__${content}`, '*');
});
},
setup(editor) {
editor.on('init', () => {
window.parent.postMessage('__LOADED__', '*');
});
},
});
window.addEventListener('message', (e) => {
const flag = '__SET_CONTENT__';
const { data } = e;
if (typeof data === 'string' && data.startsWith(flag)) {
tinymce.activeEditor.setContent(data.substring(flag.length));
}
});
有点偏离主题了,继续说vue中如何使用
这里感谢两位大哥的采坑指南。
tinymce–一款非常好用的富文本编辑器 vue集成tinymce编辑器
vue2.0使用tinymce-vue
1.如果你首先:
npm install tinymce -S
npm install @tinymce/tinymce-vue -S
那么你肯定是采坑的,因为现在tinymce 已经默认支持vue3了,所以如果vue2.0版本使用,首先应该确定版本号;
这里我用的是
npm install tinymce@5.1.0 -S
npm install @tinymce/tinymce-vue@3.0.1 -S
这两个版本是vue2.0支持的最后一个版本。
2.开始封装组件
<template>
<!-- 富文本 -->
<div>
<Editor
v-model="richTextIn"
:disabled="$attrs.disabled"
:init="init"
@onClick="onClick"
/>
</div>
</template>
<script>
import {
uploadFile,
} from '@/api/restfulApi';
import { previewUrl } from '@/utils';
import tinymce from 'tinymce/tinymce';
import Editor from '@tinymce/tinymce-vue';
import 'tinymce/themes/silver';
// import 'tinymce/icons/default/icons';
import 'tinymce/plugins/image';
import 'tinymce/plugins/media';
import 'tinymce/plugins/table';
import 'tinymce/plugins/lists';
import 'tinymce/plugins/contextmenu';
import 'tinymce/plugins/wordcount';
import 'tinymce/plugins/colorpicker';
import 'tinymce/plugins/textcolor';
import 'tinymce/plugins/preview';
import 'tinymce/plugins/code';
import 'tinymce/plugins/link';
import 'tinymce/plugins/advlist';
import 'tinymce/plugins/codesample';
import 'tinymce/plugins/hr';
import 'tinymce/plugins/fullscreen';
import 'tinymce/plugins/textpattern';
import 'tinymce/plugins/searchreplace';
import 'tinymce/plugins/autolink';
import 'tinymce/plugins/directionality';
import 'tinymce/plugins/visualblocks';
import 'tinymce/plugins/visualchars';
import 'tinymce/plugins/template';
import 'tinymce/plugins/charmap';
import 'tinymce/plugins/nonbreaking';
import 'tinymce/plugins/insertdatetime';
import 'tinymce/plugins/imagetools';
import 'tinymce/plugins/autosave';
import 'tinymce/plugins/autoresize';
export default {
components: {
Editor,
},
props: {
richText: {
type: String,
default: '',
},
// 默认插件 这里写的比较全,基本上是全部了
plugins: {
type: [String, Array],
default:
'preview searchreplace autolink directionality visualblocks visualchars fullscreen image link media template code codesample table charmap hr nonbreaking insertdatetime advlist lists wordcount imagetools textpattern autosave bdmap autoresize lineheight',
},
// 默认工具栏 这里写的比较全,基本上是全部了
toolbar: {
type: [String, Array],
default:
'code undo redo restoredraft | cut copy paste pastetext image | forecolor backcolor bold italic underline strikethrough link codesample | alignleft aligncenter alignright alignjustify outdent indent lineheight formatpainter | styleselect formatselect fontselect fontsizeselect | bullist numlist | blockquote subscript superscript removeformat | table media charmap hr pagebreak insertdatetime | bdmap fullscreen preview',
},
},
data() {
return {
// 初始化配置
init: {
// language_url: '/public/tinymce/langs/zh_CN.js',
// language: 'zh_CN',
// skin_url: '/public/tinymce/skins/ui/oxide',
height: 400,
min_height: 400,
max_height: 600,
toolbar_mode: 'wrap',
plugins: this.plugins,
toolbar: this.toolbar,
// plugins: 'preview searchreplace autolink directionality visualblocks visualchars fullscreen image link media template code',
// toolbar: 'code undo redo restoredraft | cut copy paste pastetext',
content_style: 'p {margin: 5px 0;}',
fontsize_formats: '12px 14px 16px 18px 24px 36px 48px 56px 72px',
font_formats:
'宋体=simsun,serif;仿宋体=FangSong,serif;黑体=SimHei,sans-serif;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;',
branding: false,
// 此处为图片上传处理函数,这个直接用了base64的图片形式上传图片,
// 如需ajax上传可参考https://www.tiny.cloud/docs/configure/file-image-upload/#images_upload_handler
images_upload_handler: (blobInfo, success, failure) => {
const formData = new FormData();
formData.append('file', blobInfo.blob());
// 调上传文件的接口。上传到文件服务器获取文件id和name
uploadFile(formData).then((res) => {
if (res.id) {
const { id } = res;
success(previewUrl(id));
return;
}
failure('上传失败');
})
.catch(() => {
failure('上传出错');
});
},
},
content: this.value,
};
},
computed: {
richTextIn: {
get() {
return this.richText;
},
set(e) {
this.$emit('changeRich', e);
},
},
},
mounted() {
tinymce.init({}); // 这里传个空对象就可以了
},
methods: {
onClick(e) {
this.$emit('onClick', e);
},
},
};
</script>
<style lang="scss">
.tox-tinymce-aux {
z-index: 5000 !important;
}
</style>
/**
* 预览图片
*/
export const previewUrl = fileId => `${process.env.VUE_APP_FILE}/space/${fileId}/preview`;
// 引入组件,vue组件和主题
import tinymce from 'tinymce/tinymce';
import Editor from '@tinymce/tinymce-vue';
import 'tinymce/themes/silver';
// 引入第三方插件等;
import 'tinymce/plugins/image';
import 'tinymce/plugins/media';
import 'tinymce/plugins/table';
import 'tinymce/plugins/lists';
。。。
着重说一下组件封装的图片上传问题;
在images_upload_handler中写入自己的接口调用,
这是一个类似promise的玩意儿,如果返回成功,就把展示链接放入success。在富文本端就是显示图片。
如果失败就采用failure,传入的信息会展示在富文本组件端。
images_upload_handler: (blobInfo, success, failure) => {
const formData = new FormData();
formData.append('file', blobInfo.blob());
// 调上传文件的接口。上传到文件服务器获取文件id和name
uploadFile(formData).then((res) => {
if (res.id) {
const { id } = res;
success(previewUrl(id));
return;
}
failure('上传失败');
})
.catch(() => {
failure('上传出错');
});
},
},
3.加快组件加载速度。
在index.html里,引入tinymce.min.js,路径根据自己的具体文件路径去写。
tinymce.min.js可在node_modules里找到,可以将其包括如下的文件,复制到public里边一套。
直接从publid中访问
<script src="<%= BASE_URL %>tinymce/tinymce.min.js"></script>
至此父组件引用他就可以了:
<Tinymce
:rich-text="rowItem.substance"
:disabled="isDetails"
@changeRich="(e)=>{getSubstance(e,'substance')}"
/>
/**
* 返回组件信息
*/
getSubstance(e, name) {
this.rowItem[name] = e;
},
畅快使用吧!