Quill编辑器插⼊⾃定义HTML记录的⽰例详解
转眼已经2020年,饥渴的⼈类不再满⾜于简单的⽂本,于是有了花⾥胡哨的携带各种样式的⽂本,然⽽有⽂本还不够,我们还需要让⽤户在编辑的时候,能够插⼊各种⾃定义消息类型,让我们发出去的软⽂更加好看,因此有了这篇⽂章。
前⾔
由于Quill编辑器⾃带的富⽂本过滤(⼤部分主流编辑器都会对富⽂本进⾏过滤处理),导致开发者想要配置⾃定义HTML模板时,遇到了不少⿇烦。
⼀、Quill渲染逻辑分析
为了⾃定义Quill中的HTML块内容,⾸先需要了解Quill内部的渲染流程,这⾥有⼏个关键的概念需要了解:
1、Delta
Delta是Quill内部定义的⼀个数据格式,⽤于表⽰⽂档内容以及⽂档修改操作,易读且格式简单,通过Delta的形式来维护⽂档内容,HTML内容和Delta两者可以相互转化。
举个例⼦:
这样⼀段富⽂本会被表⽰成以下的格式:
{
"ops":[
{"insert":"this is a simple text.\\nbut when "},
{"attributes":{"bold":true},"insert":"it is "},
{"insert":"not bold.\\nlet me try "},
{"attributes":{"italic":true},"insert":"italic "},
{"insert":"haha\\nwhat about "}, {"attributes":
{"italic":true,"bold":true},"insert":"both"},
{"insert":" ?\\n"} ]
}"
普通的⽂本会被定义成⼀个个的insert动作,每⼀项代表这⼀个delta,都是对⽂本内容的描述。
类似的,如果修改和删除也会⽣成对应的delta,之后会将新⽣成的change delta,与原有的delta进⾏合并操作,⽣成新的delta。(delta中⼀共包含三种操作:insert、delete、retain)
保留前10个字符,对后续的20个字符进⾏加粗操作的delta如下:
{
"ops": [
{ "retain":  },
{ "retain": , "attributes": { "bold":  } }
]
}
保留前10个字符,对后续的20个字符进⾏删除操作如下:
{
"ops": [
{ "retain":  },
{ "delete":  }
]
}
2、Parchment
Parchment是抽象的⽂档模型,对Blot进⾏管理。
将Parchment理解成完整的DOM树结构的话,那么Blot就是其中⼀个个单⼀的节点。⽽Blot去了Quill中默认的以外,还允许我们进⾏⾃定义,给了更⼤的扩展空间。
3、Blot
Blot是Parchment⽂档的组成部分,相当于对DOM节点类型的抽象,⽽⼀个具体的Blot实例⾥仍有其他的节点信息。
全局的根节点Blot是由Quill内部⾃定义的Scroll类型Blot,管理其下⾯的所有Blot。
Quill中默认定义的Blot如下:
这其中常见的包括TextBlot(⾏内普通⽂本)、Inline(⾏内携带样式的普通⽂本)、Block(块级⾏,⼀般以段落p为单位)、Break(换⾏)、Image(图⽚IMG插⼊)、Bold(加粗⽂本)。
⽽⼀段HTML如何构建出Blot?Quill中会根据节点类型优先排除⽂本节点,如果是元素节点会根据节点的ClassName进⾏再次判断,如果仍然⽆法到匹配的BlotName,则默认匹配以下的映射关系,来到对应的BlotClass。
4、Delta的实际意义
既然已经有Blot可以来表⽰我们的内容结构了,为什么还需要Delta?Delta本⾝只是⼀份内容数据的维护,也就是说HTML的更新,⽆论是⽤户输⼊,还是API操作,都会同步更新到Delta中,⽽Delta如果不作为HTML的数据源的话,那么维护⼀份Delta数据的意义⼜在哪⾥?
如果HTML => Delta,⽽不存在Delta=>HTML,那么不停地去维护⼀份delta的意义是什么?
1、由Delta⽣成HTML其实是存在的,只不过应⽤场景只限于初始化⽂档的时候,Quill会对传⼊的初始化HTML字符串进⾏解析处理,⽣成对应的Delta,其次通过applyDelta的⽅式,⽣成DOM节点回显与页⾯中。
2、看到这⾥你可能还不满意,为啥⾮要⾛这⼀步流程,初始化的时候直接⼀段字符串
5、编辑器渲染与更新流程
对于内容的修改⼀共有以下3种⽅式:
1、初始化编辑器内容:初始化调⽤quill.pasteHTML,经过HTML过滤和解析回显到编辑框中。
2、Input Event:⽤户输⼊和编辑操作,通过MutationObserver监听处理,更新delta。
3、API调⽤:调⽤内部提供API,通过modify⽅法,⽽后调⽤全局Scroll实例的⽅法去修改。
⼆、插⼊⾃定义HTML块
由于⽂章内容越来越多样化,在⽂章插⼊地图、⾳乐播放器、⼴告⾯板等需求的存在,让我们需要对富⽂本编辑器扩展出更多的功能。但是同时也要做好xss防护攻击。
按照第⼀部分的讲述,我们需要插⼊⼀个⾃定义HTML块,同时⼜要Quill能够识别,聪明的你⼀定想到了,我们需要⾃定义⼀个Blot。通过定义好Blot的⽅式,让Quill在初始化的时候能够识别我们的HTML块展⽰,同时也让我们在插⼊HTML块的时候不会被Quill进⾏脏HTML过滤。
注册Blot⽅法如下:
export default function (Quill) {
// 引⼊源码中的BlockEmbed
const BlockEmbed = Quill.import('blots/block/embed');
// 定义新的blot类型
class AppPanelEmbed extends BlockEmbed {
static create(value) {
const node = ate(value);
node.setAttribute('contenteditable', 'false');
node.setAttribute('width', '100%');
//  设置⾃定义html
node.innerHTML = ansformValue(value)
return node;
}
static transformValue(value) {
let handleArr = value.split('\n')
handleArr = handleArr.map(e => e.replace(/^[\s]+/, '')
.
replace(/[\s]+$/, ''))
return handleArr.join('')
}
// 返回节点⾃⾝的value值⽤于撤销操作
static value(node) {
return node.innerHTML
}
}
// blotName
AppPanelEmbed.blotName = 'AppPanelEmbed';
// class名将⽤于匹配blot名称
AppPanelEmbed.className = 'embed-innerApp';
// 标签类型⾃定义
AppPanelEmbed.tagName = 'div';
}
接下来你只需要这样调⽤,便可以在编辑器中插⼊⾃定义的HTML块:
quill.Selection().index || 0, 'AppPanelEmbed', `
<div class="app_card_header">
⾃定义⾯板标题
</div>
<div class="app_card_content">
⾃定义⾯板内容
</div>
<div class="app_card_footer">
footer
</div>
`);
传参格式要求如下:
insertEmbed(index: Number, type: String, value: any, source: String \= 'api'): Delta
由于contenteditable属性放开,为了防⽌造成xss攻击,所以需要我们对该属性做特殊的过滤处理,这⾥以xss模块处理为例:handleWithXss(content) {
const options = {
whiteList: {
...
div: ['class', 'style', 'data-id','contenteditable'],
...
},
css: {
whiteList: {
color: true,
'background-color': true,
'max-width': true,
},
},
stripIgnoreTag: true,
onTagAttr: (tag, name, value, isWhiteAttr) => {
// 针对div的contenteditable 处理
if (isWhiteAttr && tag === 'div' && name === 'contenteditable') {
html富文本框return 'contenteditable="false"';
}
},
} // ⾃定义规则
const myxss = new xss.FilterXSS(options)
return myxss.process(content)
}
到此这篇关于Quill编辑器插⼊⾃定义HTML记录的⽂章就介绍到这了,更多相关Quill编辑器⾃定义HTML内容请搜索以前的⽂章或继续浏览下⾯的相关⽂章,希望⼤家以后多多⽀持!

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。