「富文本」从 Quill 到 TinyMCE,我爱过恨过,也哭过笑过...

简介: 「富文本」从 Quill 到 TinyMCE,我爱过恨过,也哭过笑过...

致起始 — 本文其实是冒险故事?!


大家好,我是大寒草 🌿,为什么说我是大寒草呢,因为我这两天被富文本搞的头都大了,一个接一个出乎意料的 bug 的出现迫使我经历了:


  • 用旧爱 Quill 踩坑
  • 被迫寻找新欢
  • 用新欢 TinyMCE 踩坑


所以本篇文章表面上虽然是踩坑实践之路,但是其实是一部充满三方势力爱恨纠葛的冒险故事。


致 Quill — 我并肩作战的旧爱


网络异常,图片无法展示
|


故事的最开始是我们组接到这样的一个需求,将原本仅用于展示的邮件模板支持富文本编辑,之前我们系统里已经存在着一个基于 Quill 封装的组件,我得到的话是:“直接用那个组件就好了啊”。


所以第一步很 easy 嘛,拿来主义好,但是事情渐渐偏离了我最初的设想,我遇到的第一个问题开始了!


BUG1: 实际邮件中样式无法生效


没过多久,我就收到了第一个 bug,在富文本中修改的样式,并没有在实际发送的邮件中生效!


我收到这个 bug 的时候就很懵逼,这个基于 Quill 封装的组件在之前的业务里就是用来编辑邮件正文的,为什么偏偏在我这里就出问题了!


这个时候我是怀疑自己的


但是经过我的检查,唔,这个bug 算是历史遗留了,于是我就开始寻找问题原因。


真相永远只有一个


网络异常,图片无法展示
|


富文本中的样式是通过 class 来写的,然而且不说邮件中兼不兼容 class,我们编辑完传给服务端的富文本本身就不会携带 Quill 中的样式。


第一反应看官网,看看有没有将 class 转换为 inline 样式的配置。果然,功夫不负聪明小伙儿,我在官方文档中看到了这样一段:


网络异常,图片无法展示
|


原来如此,只要从 'attributors/style/xxx' 中引用并注册就可以转换为行内样式,兴致冲冲的我就去看 Quill 的源码,看到后我甚是灰心。


网络异常,图片无法展示
|


仅支持:


  • align
  • background
  • color
  • direction
  • font
  • size


然而实际用到的却比这几个多,比如:缩进。


其实这个时候我就已经在寻找 Quill 的替代品了,TinyMCE 就是这个时候找到的。


然而产品说了一句:“可以接受”,产品姐姐不仅减少了我的工作量,还为我和 Quill 的故事续了一波。


BUG2: 部分邮件模板内容无法于富文本中显示


刚刚由于产品的宽容,我和 Quill 的爱恨纠葛得以延续。但是接下来出现的 bug 使得我不得不抛弃我挚爱的 Quill。


产品:“我刚才去线上测试,为什么有一部分内容没有显示出来?”

我当时的第一反应是:“测试又乱改数据了?”


没错,我这个愚蠢的人类居然认为问题如此简单。


然而经过定位,我发现无法显示的内容是 ul 内部嵌套 ol,接着我先会去思考是否为我们对于组件的二次封装又问题,就去官网进行尝试:


网络异常,图片无法展示
|


也不行,于是我就有理由认为,继续使用 quill,我们是无法将 ul 内部嵌套 ol 的结构回显出来的。由于项目紧急,我便下定决心,暂时采用别的富文本绕过这个 bug


vue-quill 其实是没有这个问题的,我也很疑惑 🤔~如果有机会我会给出这个问题的答案 ✨


最后


终到曲中人散时,对不起 Quill 💔,只能说爱过,还会爱。任务紧急,实在抱歉。


致 TinyMCE — 我又爱又恨的新欢


网络异常,图片无法展示
|


Why TinyMCE


为什么选择 TypeMCE,在选择富文本组件时需要保证两点:

  • 该富文本组件需要支持全部实战化系统富文本中的既有功能
  • 可以解决上文中两个问题,即全部样式支持 inline 模式,以及可以正常显示 ul 嵌套 ol的 dom 结构


还有,其实我又看到我们团队的另一个人曾经说过 TinyMCE 不好看又比较土。但是现在这个场景下我觉得比较好用,那就 ok 吧 ☁️


介绍


以下介绍来自中文官网


TinyMCE 是一款易用、且功能强大的所见即所得的富文本编辑器。同类程序有:UEditor、Kindeditor、Simditor、CKEditor、wangEditor、Suneditor、froala等等。


TinyMCE 的优势:


  • 开源可商用,基于LGPL2.1
  • 插件丰富,自带插件基本涵盖日常所需功能
  • 接口丰富,可扩展性强,有能力可以无限拓展功能
  • 界面好看,符合现代审美
  • 提供经典、内联、沉浸无干扰三种模式
  • 对标准支持优秀(自v5开始)
  • 多语言支持,官网可下载几十种语言。


安装


  • npm i @tinymce/tinymce-vue -S
  • npm i tinymce -S


npm 上有一个 vue 版本的 tinymce,为了更方便的在 vue 中使用,我们可以把 @tinymce/tinymce-vue 以及完整的编辑器包 tinymce 一起安装下来。


注意:vue2中不能使用 @tinymce/tinymce-vue为4以上版本;比如可以:npm install @tinymce/tinymce-vue@3.0.1 -S 而 tinymce 包的版本无所谓


使用


首先注意引用顺序:


import tinymce from 'tinymce/tinymce';
import TinymceEditor from '@tinymce/tinymce-vue';
import 'tinymce/tinymce.min.js';
import 'tinymce/themes/silver/theme';


注意:引用的顺序不一致会有问题


之后引入样式:


import 'tinymce/skins/ui/oxide/content.css';
import 'tinymce/skins/ui/oxide/content.inline.css';
import 'tinymce/skins/ui/oxide/skin.css';


注意:样式必须要引用才可以编辑器才可以正常显示,编辑器需要一个 skin !


mounted 中也需要进行初始化:


mounted () {
    tinymce.init({inline: true});
},


同时在此处配置 inline 为 true

template中使用直接用 v-model 的方式就ok了


<tinymce-editor
    v-model="editContent"
    :init="init"
/>


我在 init 中的配置如下:


{
    height: 300,
    language: 'zh_CN',
    toolbar: 'fontselect | fontsizeselect | bold italic underline strikethrough | forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist | outdent indent | link ',
    plugins: 'link lists image code table colorpicker textcolor contextmenu',
    branding: false,
    relative_urls: false,
    remove_script_host: false
};


当然如果要使用 插件就需要引用进来,引用路径如下:


import 'tinymce/plugins/image';
import 'tinymce/plugins/link';
import 'tinymce/plugins/code';
import 'tinymce/plugins/table';
import 'tinymce/plugins/lists';
import 'tinymce/plugins/contextmenu';
import 'tinymce/plugins/colorpicker';
import 'tinymce/plugins/textcolor';


注意:如果字体等下拉选择无法展示需要配置 z-index


.tox-tinymce-aux {
    z-index: 709826033 !important;
}
.tox-tinymce-inline {
    z-index: 709826032 !important;
}


致结束 - 那曲终人未散的冒险故事


网络异常,图片无法展示
|


那么,这篇文章就基本结束了,寒草给大家伙儿唱个歌吧:


✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨

最近比较烦 比较烦 比较烦
陌生的城市何处有我的期盼
挥别了家乡的伙伴「Quill」
现在的我更觉得孤单

✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨


伙伴们,欢迎关注点赞我的文章,我会为大家带来更多有趣有料的内容!

下一篇文章我们再会

相关文章
|
Web App开发 移动开发 JavaScript
使用Aliplayer在微信中播放视频的正确姿势
沐钦分享下利用aliplayer在微信中播放视频的操作方式和效果
17471 0
|
9月前
|
Web App开发 人工智能 JSON
别再手写提示词!需求澄清 + 50多专业提示词框架自动匹配,效率提升10倍!
本项目推出「prompt-optimizer」智能体,专治提示词撰写痛点:表达不清、框架难选、套用费时。支持50+全球顶尖提示词框架,自动匹配、主动澄清歧义、一键生成优化提示词,并兼容多模型。已开源Skill与Chrome插件,开箱即用。(239字)
别再手写提示词!需求澄清 + 50多专业提示词框架自动匹配,效率提升10倍!
|
8月前
|
人工智能 Apache 开发者
🧨 新年新气象|x-cmd v0.8.3:Apache 2.0、Minimax M2.5、Claude Code 一键切换
X-CMD v0.8.3 正式发布:开源协议升级为 Apache 2.0,minimax 默认模型升至 M2.5,claude 新增 `use` 命令支持全局/项目级默认模型切换,提升多厂商协同效率。
|
SQL 分布式计算 数据挖掘
从Excel到高级工具:数据分析进阶指南
从Excel到高级工具:数据分析进阶指南
739 54
|
7月前
|
人工智能 监控 Linux
OpenClaw从0到1搭建个人AI助理+公众号自动运营教程:Windows/macOS/Linux/阿里云部署+免费模型配置
OpenClaw通过Skill插件化设计,大幅降低AI自动化门槛。本文完整覆盖2026年Windows11/macOS/Linux/阿里云四大部署方案、阿里云千问与Coding Plan免费模型配置、飞书远程控制、金叉监控、公众号全自动运营等实战功能,可直接用于个人量化盯盘、内容创作、日常效率提升。后续可扩展多指标监控、定时任务、多平台推送等能力,打造专属AI助理。
2328 1
|
JavaScript 索引
Vue.js中el-table组件实现数据行删除功能,包含行索引处理
注意:当从列表中移除项目时,默认情况下列表会重新渲染,并且每一项会获得新 的 索引值。如果你依赖于特定 索引值进行其他计算或者逻辑处理,请确保更新那些依赖于旧 索引值得逻辑代码段。
675 16
|
搜索推荐 JavaScript 前端开发
单页面应用和多页面应用区别及优缺点
单页面应用和多页面应用区别及优缺点
814 1
|
JavaScript
element-ui 在vue中el-input输入框的autofocus属性失效【解决方案】
element-ui 在vue中el-input输入框的autofocus属性失效【解决方案】
1160 1
|
JavaScript UED
HTML中的<a>标签使用指南
HTML中的<a>标签使用指南
1369 6
|
Java Scala Kotlin
SpringBoot 读取配置的几种方式
本文介绍了SpringBoot中读取配置文件的几种方法,包括使用`@Value`、`Environment`和`@ConfigurationProperties`注解,以及如何通过`@PropertySource`指定配置文件位置和编码。还讲解了如何自定义工厂类以支持读取`.yaml`文件。
893 0

热门文章

最新文章