首页前端开发HTMLQuill编辑器插入自定义HTML记录的示例详解

Quill编辑器插入自定义HTML记录的示例详解

时间2024-01-27 17:03:02发布访客分类HTML浏览847
导读:收集整理的这篇文章主要介绍了Quill编辑器插入自定义HTML记录的示例详解,觉得挺不错的,现在分享给大家,也给大家做个参考。 转眼已经2020年,饥渴的人类不再满足于简单的文本,于是有了花里胡哨的携带各种样式的文本,然而有文本还...
收集整理的这篇文章主要介绍了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。

对于Blot的实现定义可以参照这里: https://github.COM/quilljs/parchment#blots

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、看到这里你可能还不满意,为啥非要走这一步流程,初始化的时候直接一段字符串document.getElementById('container').innerHTML = val不行吗,是的,可以,但是Delta的存在让用户的文档变得粒度更细小,变得易维护,变得可追溯。假如A和B同时编辑着一份文档,A删除了第二行的10个字符,不需要将文档内容全量更新,只需要提交action操作,同步自己的行为,而B这边也只需要进行冲突处理后merge即可。虽然Delta的维护让逻辑变得复杂了不少,但它的存在也让文档有了更多扩展的可能。

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 = suPEr.create(value);
          node.setattribute('contenteditable', 'false');
          node.setAttribute('width', '100%');
          //   设置自定义html      node.innerHTML = this.transformValue(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';
      Quill.register(AppPanelEmbed, true);
}
    

接下来你只需要这样调用,便可以在编辑器中插入自定义的HTML块:

quill.insertEmbed(quill.getSelection().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

这里仅仅这是个简单的示例,如果想丰富自定义Blot的功能,可以参照: https://github.com/quilljs/parchment#blots

由于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') {
                return 'contenteditable="false"';
          }
        }
,      }
 // 自定义规则      const myxss = new xss.FilterXSS(options)      return myxss.PRocess(content)    }
    

到此这篇关于Quill编辑器插入自定义HTML记录的文章就介绍到这了,更多相关Quill编辑器自定义HTML内容请搜索以前的文章或继续浏览下面的相关文章,希望大家以后多多支持!

声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!

上一篇: Layui表格选中指定行的radio单选...下一篇:html 实现tab切换的示例代码猜你在找的HTML/Xhtml相关文章 了解HTTP Headers的方方面面 图文说明2022-04-12Html分层的box-shadow效果的示例代码2022-04-12html+css实现血轮眼轮回眼特效代码2022-04-12html实现随机点名器的示例代码2022-04-12HTML中table表格拆分合并(colspanrowspan)2022-04-12HTML页面滚动时部分内容位置固定不滚动的实现2022-04-12HTML+css盒子模型案例(圆半圆等)“border-radius” 简单易上手2022-04-12HTML通过表单实现酒店筛选功能2022-04-12HTML中的表单Form实现居中效果2022-04-12HTML+CSS制作心跳特效的实现2022-04-12 其他相关热搜词更多phpjavapython程序员

若转载请注明出处: Quill编辑器插入自定义HTML记录的示例详解
本文地址: https://pptw.com/jishu/588475.html
HTML+CSS相对宽度和绝对宽度冲突时的div解决方法 Layui表格选中指定行的radio单选框并滚动到该行的实现代码

游客 回复需填写必要信息