背景
目前市面上支持vue.js的富文本很多,例如:UEditor、wangEditor、Quill等等,这里也是经过了筛选和验证的,最开始选择的是Quill,后来发现使用了它的样式,对应需要展示的客户端也需要引用它的样式才能支持,耦合性太强、果断放弃、比较坑,其他的几款也尝试过wangEditor、UEditor。最终选择使用TinyMCE(插件丰富、界面美观、且对移动端兼容也还不错)。先上官网:https://www.tiny.cloud/docs/demo/full-featured/
相关依赖
"@tinymce/tinymce-vue": "^3.2.0",
"tinymce": "^5.2.0"
接入说明
中文文档
里面介绍了各种插件的使用,以及参数的配置,可以根据需要自行查阅。
组件汉化
http://tinymce.ax-z.cn/general/localize-your-language.php
导入插件
这里选择定义一个Js(import-all.js)一次性导入所有插件,也可以选择根据自己具体情况按需导入。
const importAll = requireContext => requireContext.keys().forEach(requireContext)
try {
// 导入所有插件
importAll(require.context('../../../node_modules/tinymce/plugins', true))
} catch (err) {
console.log(err)
}
创建组件实例
- 页面部分
<template>
<div>
<editor id="tinymceEditor"
:init="tinymceInit"
v-model="content"
:key="tinymceFlag">
</editor>
</div>
</template>
<script>
- 依赖部分
import tinymce from 'tinymce/tinymce'
import Editor from '@tinymce/tinymce-vue'
// 引入应用主题
import 'tinymce/themes/silver'
// 引入应用图标
import 'tinymce/icons/default'
// 导入全部插件
import './import-all'
// 也可以自行选择其他的存储方式,换汤不换药!
// 这里为我自定义的文件上传相关资源(获取OSS连接、获取OSS上传认证、生成文件名)
import { client, getFileNameUUID } from '@/utils/ali-oss'
import { getStsPermission } from '@/api/common/common'
- 数据方法部分
export default {
name: 'Tinymce',
components: {
Editor
},
props: {
// 编辑器内容
editorContent: {
type: String,
default: ''
},
// 编辑器高度
height: {
type: Number,
default: 800
},
// 编辑器宽度
width: {
type: Number,
default: undefined
},
upload_url: {
type: String,
default: ''
},
showMenubar: {
type: Boolean,
default: true
},
toolbar: {
type: String,
default: ` undo redo
| formatselect
| bold italic strikethrough forecolor backcolor formatpainter
| link image | alignleft aligncenter alignright alignjustify
| numlist bullist outdent indent
| removeformat
| preview fullscreen code`
},
baseUrl: {
type: String,
default: ''
},
// 统一配置cdn前缀
cdnOrigin: {
type: String,
// 公共CDN
// default: 'https://cdn.jsdelivr.net/npm/tinymce@5.2.0'
// 自定义CDN(如果对样式文件具有其他特殊的修改,可以自行修改后上传到可靠地方访问)
default: 'https://static.v.xxxxxxxxx.com/system/resources/tinymce'
}
},
data() {
return {
tinymceFlag: 1,
tinymceInit: {},
content: ''
}
},
mounted() {
if (this.editorContent) {
this.content = this.editorContent
}
},
watch: {
content: {
handler() {
this.$emit('update:editorContent', this.content)
console.log('监听到数据变化')
}
},
editorContent: {
handler() {
this.content = this.editorContent
},
immediate: true
}
},
activated() {
this.tinymceFlag++
},
created() {
const _this = this
this.tinymceInit = {
// 语言包设置(参阅:http://tinymce.ax-z.cn/general/localize-your-language.php)
language_url: `${this.cdnOrigin}/langs/zh_CN.js`,
language: 'zh_CN',
// skin路径
skin_url: `${this.cdnOrigin}/skins/ui/oxide`,
content_css: `${this.cdnOrigin}/skins/ui/oxide/content.css`,
// 编辑器高度
height: this.height,
width: undefined,
// 拼写检查
browser_spellcheck: true,
// 去水印
branding: false,
// 禁用编辑器底部的状态栏
elementpath: false,
// 隐藏编辑器底部的状态栏
statusbar: false,
// 允许粘贴图像
paste_data_images: true,
image_dimensions: false,
// 隐藏最上方menu
menubar: this.showMenubar,
// 去除插件【fullpage】则去除 html head body等标签信息
plugins: `print searchreplace autolink directionality visualblocks
visualchars template codesample charmap hr pagebreak nonbreaking anchor toc insertdatetime
wordcount textpattern help advlist table lists paste preview fullscreen image imagetools code link`,
toolbar: this.toolbar,
/** 处理文件图片文件上传 */
async images_upload_handler(blobInfo, success, failure) {
// 这里属于 具体的 自行上传的业务逻辑
// 包括但不限于 OSS、 COS、 七牛云等前端WEB直传
// 或者传输文件到各自服务器
}
}
}
}
组件应用示例
这里支持获取编辑器富文本内容、纯文本内容,对应html、text动态绑定。
<el-form-item label="文章内容" prop="content">
<tinymce v-if="open"
:html-content.sync="form.contentHtml"
:text-content.sync="form.content">
</tinymce>
</el-form-item>
效果预览
编辑器窗口
上传图片效果
内容小窗口预览
遇到的问题及解决方案
在dialog(弹窗)层级、遮挡问题
- 找到依赖包下,如图位置,将其skins文件夹拷贝到本地或项目的pubilc下
- 将
skin.min.css
中的z-index的值由原本的1300修改到5000及以上,这里以5000为准
- 放在本地引用或者自行上传到云存储中引用即可解决遮挡问题。
预览效果宽度调整问题
通过浏览器调试发现,是由外层一个.tox .tox-dialog--width-lg
样式块限定了最大宽度,将其删掉或指定具体数值即可。
图片自动增加宽度不能自适应问题
在设置tinymceInit
初始化时,指定下方参数为禁用
image_dimensions: false
Q.E.D.