Table of Contents
这篇文章记录一下 TinyMCE 在 vue 项目的中的运用。其实早就改写了,但一直……忽略了。这次项目迭代又用到了 TinyMCE,所以补作此文。
为什么选择 TinyMCE
TinyMCE 是一个功能齐全、历史悠久、持续维护的富文本编辑器。该编辑器为美国 Tiny Technologies 开发。wordpress 在切换为古腾堡编辑器之前就是使用的 TinyMCE。因此,项目选择了这个经过长久实践的编辑器。
安装包
首先,需要安装 TinyMCE。
yarn add tinymce
因为是 vue 项目,为了更方便地使用,安装一下 vue 的封装包。
yarn add @tinymce/tinymce-vue
使用
为了项目里各处使用,封装一个 Tinymce 组件
<template> <div class="tinymce-container"> <editor id="tinymce" v-model="value" :init="init" /> </div> </template> <script> import tinymce from 'tinymce' import Editor from '@tinymce/tinymce-vue' import 'tinymce/themes/silver/theme' import 'tinymce/plugins/image' import 'tinymce/plugins/link' import 'tinymce/plugins/code' import 'tinymce/plugins/table' import 'tinymce/plugins/lists' import 'tinymce/plugins/wordcount' import 'tinymce/icons/default' import Compressor from 'compressorjs' import { uploadFile } from '@/api/common' // 下面的插件是自带的,不需要引入 // import "tinymce/plugins/contextmenu"; // import "tinymce/plugins/colorpicker"; // import "tinymce/plugins/textcolor"; export default { name: 'MyTinymce', components: { Editor }, props: { tinymceHtml: { type: String, default: '' }, tinymceHeight: { type: Number, default: 500 } }, data() { return { value: this.tinymceHtml, // 父组件通过ref拿到该组件的值 init: { selector: '#tinymce', // https://www.tiny.cloud/get-tiny/language-packages/ language_url: '/tinymce/langs/zh_CN.js', language: 'zh_CN', skin_url: '/tinymce/skins/ui/oxide', // 编辑器需要一个skin才能正常工作,所以要设置一个skin_url指向之前复制出来的skin文件 height: this.tinymceHeight, plugins: 'image link code table lists wordcount', // 引入插件 toolbar: 'styleselect fontselect fontsizeselect lineheight link | forecolor backcolor bold italic underline strikethrough | formatselect alignleft aligncenter alignright alignjustify | image quicklink blockquote table numlist bullist | preview fullscreen', // 工具栏 browser_spellcheck: true, // 拼写检查 branding: false, // 去水印 elementpath: false, // 禁用编辑器底部的状态栏 statusbar: false, // 隐藏编辑器底部的状态栏 paste_data_images: true, // 允许粘贴图像 menubar: false, // 隐藏最上方menu toolbar_mode: 'wrap', file_picker_types: 'image', images_upload_credentials: true, fontsize_formats: '14px 16px 18px 20px 24px 26px 28px 30px 32px 36px', // 字体大小 font_formats: '微软雅黑=Microsoft YaHei,Helvetica Neue;PingFang SC;sans-serif;苹果苹方=PingFang SC,Microsoft YaHei,sans-serif;宋体=simsun;serifsans-serif;Terminal=terminal;monaco;Times New Roman=times new roman;times', // 字体 lineheight_formats: '1 1.1 1.2 1.3 1.4 1.5 2', // 行高 style_formats: [ { title: '段落间距', // items: [ // { // title: '1', block: 'p', styles: { 'margin-top': '1em', 'margin-bottom': '1em' } // } // ] items: [0, 1, 2, 3, 4, 5, 10, 15, 20, 25, 30, 35, 40].map(item => { return { title: `${item}px`, block: 'p', styles: { 'margin-top': `${item}px`, 'margin-bottom': `${item}px` } } }) } ], style_formats_merge: true, // 自定义样式追加到 styleselect style_formats_autohide: true, // 隐藏不可用样式 /** * 下面方法是为tinymce添加自定义插入图片按钮 */ // 图片上传三个参数,图片数据,成功时的回调函数,失败时的回调函数 images_upload_handler: function(blobInfo, success, failure) { // 图片压缩 new Compressor(blobInfo.blob(), { quality: 0.75, maxWidth: 1920, success: (result) => { _uploadFile(new File([result], result.name, { type: result.type })) }, error: () => { _uploadFile(blobInfo.blob()) } }) function _uploadFile(blobData) { const formdata = new FormData() formdata.append('file', blobData) formdata.append('type', 'product') uploadFile(formdata) .then(res => { console.log(res) success(res.data.url) }) .catch(res => { failure('error') }) } } } } }, computed: {}, watch: { tinymceHtml(newV, oldV) { this.value = newV } }, created() {}, mounted() { tinymce.init({}) }, methods: {} } </script> <style lang="scss"> .tox-silver-sink, .tox-tinymce-aux { z-index: 3000000 !important; } .tox .tox-dialog-wrap__backdrop--opaque { background-color: transparent !important; } </style>
(这里的大部分代码也是拷贝的其他人的)
说明一下。
tinymce 需要有主题才能显示,这里把主题拷贝到了项目静态资源目录引用。原因忘了,大概是避免打包遗漏吧。
语言文件到 tinymce 网站下载。
style_formats:可以进行样式自定义。我这里定义了段落间距。tinymce 没有提供相关功能,只能自己定义。可以用,但效果不太好。使用后会把选中的部分标签都变成 p 标签,并应用相关 margin 设置。
style_formats_merge:把自定义的样式追加到样式文件。
images_upload_handler:这里可以进行图片压缩的操作,避免上传图片太大。我使用的图片压缩包是 compressorjs
样式部分的 z-index 是为了避免 element-ui 弹窗 z-index 过高而导致 tinymce 显示问题。
总结
web 的富文本编辑体验并不是很好,与 word 相差甚远。将就用吧。