DevUI 是一款面向企业中后盾产品的开源前端解决方案,它提倡沉迷灵便至简的设计价值观,提倡设计者为实在的需要服务,为少数人的设计,回绝哗众取宠、取悦眼球的设计。如果你正在开发 ToB工具类产品,DevUI 将是一个很不错的抉择!

引言

富文本编辑器大略是最简单、应用场景却极广的组件了。

能够说富文本编辑器让Web数据录入充斥了有限的设想空间,如果只有文本框、下拉框这些纯文本的数据录入组件,那么Web的数据录入能力将极大地受限。咱们将无奈在网页上插入图片、视频这些富文本内容,更无奈插入自定义的内容。

富文本编辑器让Web内容编辑变得更轻松、更高效,咱们简直能够在富文本编辑器中插入任何你想插入的内容,图片、视频、超链接、公式、代码块,都不在话下,甚至还能够插入表格、PPT、思维导图,甚至3D模型这种超简单的自定义内容。

富文本编辑器的场景在Web上也是随处可见,写文章、写评论、意见反馈、录需要单,都须要应用到富文本。

本文联合DevUI团队在富文本组件中的实际,从应用场景、技术选型,再到对Quill的扩大,以及Quill的基本原理,跟大家分享Quill富文本编辑器的那些事儿。

本文次要由以下局部组成:

  1. 富文本编辑器的应用场景
  2. 技术选型
  3. 咱们为什么抉择Quill
  4. 如何扩大Quill
  5. Quill基本原理

以下内容来自Kagol华为 HWEB 大前端技术分享会上的演讲。

富文本编辑器的应用场景

  • 博客文章
  • Wiki词条
  • 工作项形容
  • 测试用例步骤
  • 反馈意见
  • 评论

技术选型

咱们的需要:

  • 开源协定敌对
  • Angular框架或框架无关
  • 灵便可扩大
  • 反对插入/编辑表格和图片
  • 插件丰盛,生态好

选型剖析

  • 首先排除官网不保护的UEditor
  • 而后排除React框架专属的Draft.jsSlate
  • 接着排除开源协定不敌对的CKEditor
  • 因为咱们的业务场景丰盛,须要富文本插入/编辑表格的性能,所以还须要排除不反对表格的Trix,弱反对表格的EtherpadProsemirror,以及表格性能免费的TinyMCE
  • 最初只剩下QuillwangEditor两款编辑器可选,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!