共计 3942 个字符,预计需要花费 10 分钟才能阅读完成。
DevUI 是一款面向企业中后盾产品的开源前端解决方案,它提倡 沉迷
、 灵便
、 至简
的设计价值观,提倡设计者为实在的需要服务,为少数人的设计,回绝哗众取宠、取悦眼球的设计。如果你正在开发 ToB
的 工具类产品
,DevUI 将是一个很不错的抉择!
引言
富文本编辑器大略是最简单、应用场景却极广的组件了。
能够说富文本编辑器让 Web 数据录入充斥了有限的设想空间,如果只有文本框、下拉框这些纯文本的数据录入组件,那么 Web 的数据录入能力将极大地受限。咱们将无奈在网页上插入图片、视频这些富文本内容,更无奈插入自定义的内容。
富文本编辑器让 Web 内容编辑变得更轻松、更高效,咱们简直能够在富文本编辑器中插入任何你想插入的内容,图片、视频、超链接、公式、代码块,都不在话下,甚至还能够插入表格、PPT、思维导图,甚至 3D 模型这种超简单的自定义内容。
富文本编辑器的场景在 Web 上也是随处可见,写文章、写评论、意见反馈、录需要单,都须要应用到富文本。
本文联合 DevUI 团队在富文本组件中的实际,从应用场景、技术选型,再到对 Quill 的扩大,以及 Quill 的基本原理,跟大家分享 Quill 富文本编辑器的那些事儿。
本文次要由以下局部组成:
- 富文本编辑器的应用场景
- 技术选型
- 咱们为什么抉择 Quill
- 如何扩大 Quill
- Quill 基本原理
以下内容来自 Kagol
在华为 HWEB 大前端技术分享会
上的演讲。
富文本编辑器的应用场景
- 博客文章
- Wiki 词条
- 工作项形容
- 测试用例步骤
- 反馈意见
- 评论
- …
技术选型
咱们的需要:
- 开源协定敌对
- Angular 框架或框架无关
- 灵便可扩大
- 反对插入 / 编辑表格和图片
- 插件丰盛,生态好
选型剖析
- 首先排除官网不保护的
UEditor
- 而后排除 React 框架专属的
Draft.js
和Slate
- 接着排除开源协定不敌对的
CKEditor
- 因为咱们的业务场景丰盛,须要富文本插入 / 编辑表格的性能,所以还须要排除不反对表格的
Trix
,弱反对表格的Etherpad
和Prosemirror
,以及表格性能免费的TinyMCE
- 最初只剩下
Quill
和wangEditor
两款编辑器可选,wangEditor
的扩展性和生态不如Quill
,所以最终抉择Quill
作为富文本组件的基座
为什么抉择 Quill?
- BSD 协定,商业敌对
- 文档具体,上手快
- API 驱动,扩展性好
- 插件丰盛,生态好
文档具体
Document:https://quilljs.com/
介绍 Quill 的 API:
介绍如何扩大 Quill:
上手快
- 装置 Quill:
npm i quill
- 引入款式:
@import 'quill/dist/quill.snow.css';
- 引入 Quill:
import Quill from 'quill';
- 初始化 Quill:
new Quill('#editor', { theme: 'snow'});
效果图:
API 驱动,扩展性好
插件丰盛,生态好
扩大 Quill
插入标签
比方我想在编辑器里插入标签
上传附件
比方我想在编辑器里插入附件
插入表情
比方我想在编辑器中插入表情
相似语雀的评论:https://www.yuque.com/yuque/blog/sguhed
共性分割线
比方我想插入 B 站这种个性化的分割线
超链接卡片
比方我想插入知乎这样的超链接卡片
如何插入表情?
咱们从如何插入表情动手,一起看看怎么在 Quill 中插入自定义的内容。
要在 Quill 中插入表情,只须要以下四步:
- 第一步:自定义工具栏按钮
- 第二步:自定义 Blot 内容 EmojiBlot
- 第三步:在 Quill 注册 EmojiBlot
- 第四步:调用 Quill 的 API 插入表情
第一步:自定义工具栏按钮
const quill = new Quill('#editor', {
theme: 'snow',
modules: {
// 配置工具栏模块
toolbar: {container: [ …, [ 'emoji'] ], // 减少一个按钮
handlers: {
// 增加按钮的解决逻辑
emoji() {console.log('插入表情');
}
}
},
}
});
给工具栏按钮减少图标
// 扩大 Quill 内置的 icons 配置
const icons = Quill.import('ui/icons');
icons.emoji =‘<svg>…</svg>’; // 图标的 svg 能够从 iconfont 网站复制
成果如下:
工具栏上曾经多了一个表情的按钮,并且可能响应鼠标点击事件,下一步就是要
编写插入表情的具体逻辑,这波及到 Quill 的自定义内容相干的常识。
第二步:自定义 Blot 内容 EmojiBlot
Quill 中的 Blot 就是一个一般的 ES6 Class,因为表情和图片的差异就在于:
Quill 内置的图片格式不反对自定义宽高,而咱们要插入的表情是须要特定的宽高的。
因而咱们能够基于 Quill 内置的 image 格局来扩大。
emoji.ts
import Quill from 'quill';
const ImageBlot = Quill.import('formats/image');
// 扩大 Quill 内置的 image 格局
class EmojiBlot extends ImageBlot {
static blotName = 'emoji'; // 定义自定义 Blot 的名字(必须全局惟一)static tagName = 'img'; // 自定义内容的标签名
// 创立自定义内容的 DOM 节点
static create(value): any {const node = super.create(value);
node.setAttribute('src', ImageBlot.sanitize(value.url));
if (value.width !== undefined) {node.setAttribute('width', value.width);
}
if (value.height !== undefined) {node.setAttribute('height', value.height);
}
return node;
}
// 返回 options 数据
static value(node): any {
return {url: node.getAttribute('src'),
width: node.getAttribute('width'),
height: node.getAttribute('height')
};
}
}
export default EmojiBlot;
第三步:在 Quill 注册 EmojiBlot
有了 EmojiBlot,要将其插入 Quill 编辑器中,还须要将这个 ES6 类注册到 Quill 中。
import EmojiBlot from './formats/emoji';
Quill.register('formats/emoji', EmojiBlot);
第四步:调用 Quill 的 API 插入表情
EmojiBlot 注册到 Quill 中之后,Quill 就能意识它了,也就能够调用 Quill 的 API 将其插入到编辑器中。
emoji(): void {console.log(‘插入表情 ');
// 获取以后光标地位
const index = this.quill.getSelection().index;
// 在以后光标处插入 emoji(blotName)this.quill.insertEmbed(index, 'emoji', {
url: 'assets/emoji/good.png',
width: '64px',
});
},
效果图
Demo 源码
源码链接:https://gitee.com/kagol/quill-demo
也欢送关注咱们 DevUI 组件库的官网,理解更多乏味又实用的开源组件!
DevUI 官网:https://devui.design
Quill 基本原理
最初讲一讲 Quill 的基本原理。
基本原理
- 应用 Delta 数据模型形容富文本内容及其变动,以保障行为的可预测
- 通过 Parchment 对 DOM 进行形象,以保障平台一致性
- 通过 Mutation Observe 监听 DOM 节点的变动,将 DOM 的更改同步到 Delta 数据模型中
Quill 如何表白编辑器内容?
Delta 数据模型
通过 Delta 数据模型来形容富文本内容及其变动
Delta 是 JSON 的一个子集,只蕴含一个 ops 属性,它的值是一个对象数组,每个数组项代表对编辑器的一个操作(以编辑器初始状态为空为基准)。
{
"ops": [{ "insert": "Hello"},
{"insert": "World", "attributes": { "bold": true} },
{"insert": "\n"}
]
}
批改编辑器内容
比方咱们把加粗的 ”World” 改成红色的文字 ”World”,这个动作用 Delta 形容如下:
{
"ops": [{ "retain": 6},
{"retain": 5, "attributes": { "color": "#ff0000"} }
]
}
意思是:保留编辑器最后面的 6 个字符,即保留 ”Hello “ 不动,保留之后的 5 个字符 ”World”,并将这些字符设置为字体色彩为 ”#ff0000″。
删除编辑器内容
如果要删除 ”World” 呢?
{
"ops": [{ "retain": 6},
{"delete": 5}
]
}
即:保留后面 6 个字符(’Hello’),删除之后的 5 个字符(’World’)
Quill 如何渲染内容?
渲染富文本内容的基本原理:
遍历 Delta 数组,将其中形容的内容一个一个利用(插入 / 格式化 / 删除)到编辑器中。
详情可参考 DevUI 专栏文章:
《Quill 的内容渲染机制》
Quill 如何扩大编辑器的能力?
扩大 Quill 的形式:
- 通过自定义 Blot 格局来扩大编辑器的内容
- 通过自定义模块来扩大编辑器的性能
详情可参考 DevUI 专栏文章:
《古代富文本编辑器 Quill 的模块化机制》
THANK YOU!