关于devui:通过-Quill-API-实现对编辑器内容的完全控制附有查找替换功能的实现

57次阅读

共计 7353 个字符,预计需要花费 19 分钟才能阅读完成。

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

以下文章和本文相干,兴许你也会喜爱:

《古代富文本编辑器 Quill 的模块化机制》

《Quill 富文本编辑器的实际》

《如何将龙插入到编辑器中?》

《明天是儿童节,整个贪吃蛇到编辑器里玩儿吧》

《古代富文本编辑器 Quill 的内容渲染机制》

《Quill 根本应用和配置》

引言

这是深入浅出 Quill 系列的第 2 篇。

上一篇咱们介绍了 Quill 的根本应用和配置,置信大家可能应用 Quill 搭建一个简略的富文本编辑器啦。

不过理论的业务场景可能更简单,有更多定制的需要,Quill 是否满足呢?

Quill 是一款 API 驱动的富文本编辑器,它的内容能够通过 API 实现齐全的掌控,咱们一起来看看吧。

1 对内容的管制

富文本编辑器最根本的操作就是对内容的 ///,比方:

  • 在编辑器某处减少一些文本
  • 选中编辑器中的一部分内容,将其删除
  • 选中一部分文本,给它增加某种格局
  • 获取其中一部分内容,对其进行转换

以上操作间接通过键盘和鼠标很容易操作,然而通过 API 如何实现呢?

1.1 删

先看 的局部,通过 deleteText() 办法实现,该办法次要有两个入参:

  • index 从哪儿删除
  • length 删除多少内容

比方我想把上面的 Hello 删除:

this.quill.deleteText(0, 6);

又比方我想删除编辑器里的所有内容,但咱们不晓得外面一共有多少内容,是不是须要一个一个数一下呢?

其实是不须要的,Quill 提供了一个查问编辑器总字符数的办法 getLength()(前面介绍的局部也会讲到)。

所有删除所有内容也很简略:

this.quill.deleteText(0, this.quill.getLength());

还有一种常见的状况,就是咱们想删除编辑器中选中的内容,这要如何实现呢?

Quill 提供了一个获取编辑器选区的办法 getSelection()(前面介绍 对选区的管制 时会讲到)能够轻松实现:

// 获取选区内容所在的 index 和 length
const {index, length} = this.quill.getSelection();

this.quill.deleteText(index, length);

是不是十分不便呢?

1.2 查

再来看 的局部,Quill 托管了编辑器里所有的内容,因而它对外面的内容一目了然,Quill 晓得:

  • 指定地位有什么内容
  • 有多少内容
  • 它的格局是什么

能够应用 getText() 办法获取纯文本内容,它的应用形式也后面介绍过的 deleteText()removeFormat()也相似:

// 获取指定地位的文本
this.quill.getText(0, 6);

// 不传入任何参数,能够获取全副文本
this.quill.getText();

// 获取选中文本
const {index, length} = this.quill.getSelection();
this.quill.getText(index, length);

都晓得有什么内容了,拿到内容的长度就很简略了:

const length = this.quill.getText().length;

Quill 提供了一个简便的办法getLength(),能够间接拿到全副文本的长度:

const length = this.quill.getLength();

要获取选中文本的长度,能够应用之前介绍过的 getSelection() 办法:

const length = this.quill.getSelection().length;

1.3 增

1.3.1 插入文本

往编辑器里减少格式化的内容是最常见的需要,Quill 针对该场景提供了十分丰盛的 API,最根底的就是 insertText() 办法。

该办法即能够减少纯文本,又能够减少带格局的文本。

插入纯文本须要传入两个参数:

  • index 从哪个地位插入文本
  • text 插入什么文本
this.quill.insertText(0, 'DevUI 是一款面向企业中后盾产品的开源前端解决方案');

插入带格局的文本须要额定传入两个参数:

  • format 格局的名字
  • value 格局的值

比方我想在以后光标前面插入一个带超链接的DevUI

const range = this.quill.getSelection();
if (range) {this.quill.insertText(range.index, 'DevUI', 'link', 'https://devui.design/');
}

1.3.2 插入嵌入内容

插入嵌入内容的办法insertEmbed(),置信大家都很相熟了,我在之前的

  • 《Quill 富文本编辑器的实际》
  • 《如何将龙插入到编辑器中?》
  • 《明天是儿童节,整个贪吃蛇到编辑器里玩儿吧》
    三篇文章中屡次应用这个 API。

这个办法和 insertText() 的区别在于没有第二个参数,因为它不须要插入文本。

比方插入 B 站格调的分割线:

const index = this.quill.getSelection().index;
this.quill.insertEmbed(index, 'divider', {
  url: 'assets/images/divider.png',
  width: '660px',
});

比方插入龙:

const index = this.quill.getSelection().index;
this.quill.insertEmbed(index, 'dragon', {id: 'canvas-dragon',});

比方插入贪吃蛇小游戏:

const index = this.quill.getSelection().index;
this.quill.insertEmbed(index, 'snake', {id: 'canvas-snake',});

1.3.3 用纯文本替换现有内容

这两个办法都是在现有内容的根底上新增文本。

如果要间接用新的内容替换现有文本,要怎么做呢?

应用以下两个 set 办法即可:

  • setText 设置纯文本
  • setContents 设置带格局的文本

setText()办法只有一个参数:

  • text 须要插入的纯文本
this.quill.setText('Hello DevUI!');

如果 text 参数传入空字符串,则会清空编辑器内容:

this.quill.setText('');

1.3.4 用 delta 数据替换现有内容

setContents()办法十分弱小,能够应用指定的 delta 数据来渲染编辑器的内容。

比方咱们想要将以后富文本的内容变成一个贪吃蛇游戏:

this.quill.setContents([{ insert: { snake: { id: 'snake'} } }
]);

个别 delta 数据会存储在数据库中,应用 delta 来初始化编辑器内容时,能够应用该办法。

1.4 改

setContents()办法还有一个兄弟叫updateContents(),这俩兄弟本事都十分强。

updateContents()办法能够应用 delta 更新编辑器中的指定内容。

比方我想把选中的 Quill 内容变成 DevUI,并加上超链接,不应用updateContents() 办法的状况下,咱们须要调用多个办法:

const {index, length} = this.quill.getSelection();
this.quill.deleteText(index, length);
this.quill.insertText(index, 'DevUI', 'link', 'https://devui.design/');

咱们再来看看应用 updateContents() 办法如何实现:

this.quill.updateContents([{ retain: index},
  {delete: length},
  {insert: 'DevUI', attributes: { link: 'https://devui.design/'} }
]);

两种办法的成果一样,然而后者只须要调用一个办法。

updateContents()办法能够赋予咱们通过操作 delta 这个 JSON 数据来操作编辑器内容,而不必手动调用 API 去扭转内容,在某些场景下这将是一个极大的便当。

2 对格局的管制

2.1 删

除了能够删除编辑器内容外,咱们可能还须要革除某局部内容的格局,革除格局能够应用 removeFormat() 办法,该办法的应用形式和 deleteText() 简直是一样的,不再赘述。

// 革除指定地位和长度的文本的格局
this.quill.removeFormat(0, 6);

// 革除全副文本的格局
this.quill.removeFormat(0, this.quill.getLength());

// 革除选中文本的格局
const {index, length} = this.quill.getSelection();
this.quill.removeFormat(index, length);

2.2 查

获取繁多格局

getText()办法只能拿到纯文本,并不知道外面有什么格局,要想获取指定文本的格局,能够应用 getFormat() 办法,应用形式都一样。

// 获取选中文本的格局
const {index, length} = this.quill.getSelection();
const format = this.quill.getFormat(index, length);

比方粗体的格局:

{bold: true}

超链接的格局:

{link: "https://juejin.cn/post/6976023288753586184"}

获取 Delta 格局

不过 getFormat() 办法只能拿到繁多的格局,如果想晓得指定内容的全副格局信息,须要应用一个更加弱小的 API:getContents(),这个办法能获取内容的 delta 模式,而 delta 格局不仅形容了有什么内容,还形容了这些内容的格局是什么。

比方以下选中的内容,咱们看看它的内容和格局是什么。

调用 getContents() 办法:

const {index, length} = this.quill.getSelection();
const contents = this.quill.getContents(index, length);
console.log('contents:', contents);

打印了以下信息:

{
  ops: [{ insert: '删除内容'},
    {attributes: { header: 2}, insert: '\n' }, // 题目二格局
    {insert: '先看'},
    {attributes: { code: true}, insert: '删' }, // 行内代码格局
    {insert: '的局部,通过'},
    {attributes: { code: true}, insert: 'deleteText()'}, // 行内代码格局
    {insert: '办法实现,该办法次要有两个入参:\nindex 从哪儿删除'},
    {attributes: { list: 'bullet'}, insert: '\n' }, // 无序列表格局
    {insert: 'length 删除多少内容'},
    {attributes: { list: 'bullet'}, insert: '\n' }, // 无序列表格局
    {insert: '比方我想把上面的'},
    {attributes: { code: true}, insert: 'Hello' }, // 行内代码格局
    {insert: '删除:\nthis.quill.deleteText(0, 6);' },
    {attributes: { 'code-block': true}, insert: '\n' }, // 代码块格局
    {insert: '\n'}
  ]
}

从以上 delta 构造咱们很容易得出编辑器内容的格局信息:

  • 删除内容 是题目二格局
  • /deleteText()/Hello 是行内代码格局
  • index 从哪儿删除 length 删除多少内容 是无序列表格局
  • this.quill.deleteText(0, 6);是代码块格局
  • 其余内容都是纯文本格式

是不是高深莫测呢?

2.3 增

除了删除和查找格局之外,还能够设置格局,Quill 提供了 3 个设置格局的办法:

  • format(format, value) 设置选中文本的格局
  • formatLine(index, length, format, value) 设置航行格局
  • formatText(index, length, format, value) 设置文本格式
// 设置选中文本为粉色
this.quill.format('color', 'pink');

// 设置第 10-20 个字符为粉色
this.quill.formatText(10, 10, 'color', 'pink');

// 设置第一行为有序列表
this.quill.formatLine(0, 1, 'list', 'ordered');

3 对选区的管制

3.1 查

3.1.1 查问选区信息

获取以后选区或光标的办法getSelection(),咱们在后面曾经应用过屡次,阐明这个办法是一个十分实用的高频办法。

该办法不须要传入参数,返回以后选区信息:

  • index 选区开始地位
  • length 选区长度
{
  index: 0,
  length: 3
}

如果只有光标,没有抉择抉择任何内容,则返回的 length0

如果编辑器没有光标,则返回null

3.1.2 查问文本绝对定位地位

除了查问选区地位和长度,还能够应用 getBounds() 办法查问指定地位的文本在编辑器容器中的绝对定位地位,该办法有两个入参:

  • index 选区开始地位
  • length 选区长度

比方我想看下编辑器结尾的三个字符的地位:

const bounds = this.quill.getBounds(0, 3);

返回后果:

{
  bottom: 49.100006103515625
  height: 22.5
  left: 18
  right: 66
  top: 26.600006103515625
  width: 48
}

3.2 增

除了查看以后选区信息,咱们还能够应用 setSelection() 办法手动设置选区和光标地位,该办法有两个参数:

  • index 选区开始地位
  • length 选区长度

如果只设置第一个参数,将只设置光标地位,不选中文本:

// 将光标定位到第 10 个字符前面
this.quill.setSelection(10);

两个参数同时设置将选中文本:

// 选中第 1 到 10 个字符
this.quill.setSelection(0, 10);

选区和光标是后续操作的根底,所以该办法和 getSelection() 办法一样,是一个十分罕用的办法。

4 小结

咱们做一个简略的小结:

  • 对内容的管制

    • 删除内容 deleteText(index, length)
    • 查找内容 getText(index, length)
    • 获取编辑器内容长度 getLength()
    • 插入文本内容 insertText(index, text, format, value)
    • 插入嵌入内容 insertEmbed(index, format, value)
    • 应用纯文本替换内容 setText(text)
    • 用 delta 数据替换现有内容 setContents(delta)
    • 用 delta 更新内容 updateContents(delta)
  • 对格局的管制

    • 删除格局 removeFormat(index, length)
    • 查找繁多格局 getFormat(index, length)
    • 获取 Delta 格局 getContents(index, length)
    • 设置选中文本的格局 format(format, value)
    • 设置行格局 formatLine(index, length, format, value)
    • 设置文本格式 formatText(index, length, format, value)
  • 对选区的管制

    • 获取选区 / 光标信息 getSelection()
    • 获取指定文本的绝对定位 getBounds(index, range)
    • 设置选区 / 光标 getSelection(index, range)

5 案例:查找替换性能

最初咱们用一个查找替换的案例来温故下之前介绍过的 API。

// 待查找文本
const str = 'Quill';
const length = str.length;

// 匹配指标文本的正则
const reg = new RegExp(str, 'g');

let match;
while ((match = reg.exec(this.quill.getText())) !== null) {
  // 指标文本在文档中的地位
  const index = match.index;
  
  // 匹配到指标文本之后,咱们能够对该文本做高亮或替换的解决
  
  // 高亮
  this.quill.formatText(index, length, 'background', '#ef0fff');
  
  // 替换
  this.quill.deleteText(index, length);
  this.quill.insertText(index, 'DevUI', 'link', 'https://devui.design/');
}

小结

本文次要介绍了 Quill 的罕用 API,以及每个 API 的应用场景。

后续将介绍更多对于 Quill 的实际,关注 DevUI 不迷路🦌。

欢送加 DevUI 小助手微信:devui-official,一起探讨 Angular 技术和前端技术。

欢送关注咱们 DevUI 组件库,点亮咱们的小星星🌟:

https://github.com/devcloudfe/ng-devui

也欢送应用 DevUI 新公布的 DevUI Admin 零碎,开箱即用,10 分钟搭建一个好看大气的后盾管理系统!

退出咱们

咱们是 DevUI 团队,欢送来这里和咱们一起打造优雅高效的人机设计 / 研发体系。招聘邮箱:muyang2@huawei.com。

文 /DevUI Kagol

往期文章举荐

《Quill 根本应用和配置》

《古代富文本编辑器 Quill 的模块化机制》

《Quill 富文本编辑器的实际》

《如何将龙插入到编辑器中?》

《明天是儿童节,整个贪吃蛇到编辑器里玩儿吧》

正文完
 0