主頁 > 知識庫 > Quill編輯器插入自定義HTML記錄的示例詳解

Quill編輯器插入自定義HTML記錄的示例詳解

熱門標(biāo)簽:電話機(jī)器人批發(fā) 強(qiáng)訊外呼系統(tǒng) 長春極信防封電銷卡公司 crm外呼系統(tǒng)好不好 智能電銷機(jī)器人廣告語 電銷外呼線路改不外呼線路 重慶人工智能電銷機(jī)器人報價 愛巢地圖標(biāo)注 貴陽ai外呼系統(tǒng)

轉(zhuǎn)眼已經(jīng)2020年,饑渴的人類不再滿足于簡單的文本,于是有了花里胡哨的攜帶各種樣式的文本,然而有文本還不夠,我們還需要讓用戶在編輯的時候,能夠插入各種自定義消息類型,讓我們發(fā)出去的軟文更加好看,因此有了這篇文章。

前言

由于Quill編輯器自帶的富文本過濾(大部分主流編輯器都會對富文本進(jìn)行過濾處理),導(dǎo)致開發(fā)者想要配置自定義HTML模板時,遇到了不少麻煩。

一、Quill渲染邏輯分析

為了自定義Quill中的HTML塊內(nèi)容,首先需要了解Quill內(nèi)部的渲染流程,這里有幾個關(guān)鍵的概念需要了解:

1、Delta

Delta是Quill內(nèi)部定義的一個數(shù)據(jù)格式,用于表示文檔內(nèi)容以及文檔修改操作,易讀且格式簡單,通過Delta的形式來維護(hù)文檔內(nèi)容,HTML內(nèi)容和Delta兩者可以相互轉(zhuǎn)化。

舉個例子:

這樣一段富文本會被表示成以下的格式:

{  
"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動作,每一項(xiàng)代表這一個delta,都是對文本內(nèi)容的描述。

類似的,如果修改和刪除也會生成對應(yīng)的delta,之后會將新生成的change delta,與原有的delta進(jìn)行合并操作,生成新的delta。(delta中一共包含三種操作:insert、delete、retain)

保留前10個字符,對后續(xù)的20個字符進(jìn)行加粗操作的delta如下:

{
  "ops": [
    { "retain":  },
    { "retain": , "attributes": { "bold":  } }
  ]
}

保留前10個字符,對后續(xù)的20個字符進(jìn)行刪除操作如下:

{
  "ops": [
    { "retain":  },
    { "delete":  }
  ]
}

2、Parchment

Parchment是抽象的文檔模型,對Blot進(jìn)行管理。

將Parchment理解成完整的DOM樹結(jié)構(gòu)的話,那么Blot就是其中一個個單一的節(jié)點(diǎn)。而Blot去了Quill中默認(rèn)的以外,還允許我們進(jìn)行自定義,給了更大的擴(kuò)展空間。

3、Blot

Blot是Parchment文檔的組成部分,相當(dāng)于對DOM節(jié)點(diǎn)類型的抽象,而一個具體的Blot實(shí)例里仍有其他的節(jié)點(diǎn)信息。

全局的根節(jié)點(diǎn)Blot是由Quill內(nèi)部自定義的Scroll類型Blot,管理其下面的所有Blot。

對于Blot的實(shí)現(xiàn)定義可以參照這里: https://github.com/quilljs/parchment#blots

Quill中默認(rèn)定義的Blot如下:

這其中常見的包括TextBlot(行內(nèi)普通文本)、Inline(行內(nèi)攜帶樣式的普通文本)、Block(塊級行,一般以段落p為單位)、Break(換行)、Image(圖片IMG插入)、Bold(加粗文本)。

而一段HTML如何構(gòu)建出Blot?Quill中會根據(jù)節(jié)點(diǎn)類型優(yōu)先排除文本節(jié)點(diǎn),如果是元素節(jié)點(diǎn)會根據(jù)節(jié)點(diǎn)的ClassName進(jìn)行再次判斷,如果仍然無法找到匹配的BlotName,則默認(rèn)匹配以下的映射關(guān)系,來找到對應(yīng)的BlotClass。

4、Delta的實(shí)際意義

既然已經(jīng)有Blot可以來表示我們的內(nèi)容結(jié)構(gòu)了,為什么還需要Delta?Delta本身只是一份內(nèi)容數(shù)據(jù)的維護(hù),也就是說HTML的更新,無論是用戶輸入,還是API操作,都會同步更新到Delta中,而Delta如果不作為HTML的數(shù)據(jù)源的話,那么維護(hù)一份Delta數(shù)據(jù)的意義又在哪里?

如果HTML => Delta,而不存在Delta=>HTML,那么不停地去維護(hù)一份delta的意義是什么?

1、由Delta生成HTML其實(shí)是存在的,只不過應(yīng)用場景只限于初始化文檔的時候,Quill會對傳入的初始化HTML字符串進(jìn)行解析處理,生成對應(yīng)的Delta,其次通過applyDelta的方式,生成DOM節(jié)點(diǎn)回顯與頁面中。

2、看到這里你可能還不滿意,為啥非要走這一步流程,初始化的時候直接一段字符串document.getElementById('container').innerHTML = val不行嗎,是的,可以,但是Delta的存在讓用戶的文檔變得粒度更細(xì)小,變得易維護(hù),變得可追溯。假如A和B同時編輯著一份文檔,A刪除了第二行的10個字符,不需要將文檔內(nèi)容全量更新,只需要提交action操作,同步自己的行為,而B這邊也只需要進(jìn)行沖突處理后merge即可。雖然Delta的維護(hù)讓邏輯變得復(fù)雜了不少,但它的存在也讓文檔有了更多擴(kuò)展的可能。

5、編輯器渲染與更新流程

對于內(nèi)容的修改一共有以下3種方式:

1、初始化編輯器內(nèi)容:初始化調(diào)用quill.pasteHTML,經(jīng)過HTML過濾和解析回顯到編輯框中。

2、Input Event:用戶輸入和編輯操作,通過MutationObserver監(jiān)聽處理,更新delta。

3、API調(diào)用:調(diào)用內(nèi)部提供API,通過modify方法,而后調(diào)用全局Scroll實(shí)例的方法去修改。

二、插入自定義HTML塊

由于文章內(nèi)容越來越多樣化,在文章插入地圖、音樂播放器、廣告面板等需求的存在,讓我們需要對富文本編輯器擴(kuò)展出更多的功能。但是同時也要做好xss防護(hù)攻擊。

按照第一部分的講述,我們需要插入一個自定義HTML塊,同時又要Quill能夠識別,聰明的你一定想到了,我們需要自定義一個Blot。通過定義好Blot的方式,讓Quill在初始化的時候能夠識別我們的HTML塊展示,同時也讓我們在插入HTML塊的時候不會被Quill進(jìn)行臟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%');
      //   設(shè)置自定義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('')
    }

    // 返回節(jié)點(diǎn)自身的value值 用于撤銷操作
    static value(node) {
      return node.innerHTML
    }
  }
  // blotName
  AppPanelEmbed.blotName = 'AppPanelEmbed';
  // class名將用于匹配blot名稱
  AppPanelEmbed.className = 'embed-innerApp';
  // 標(biāo)簽類型自定義
  AppPanelEmbed.tagName = 'div';
  Quill.register(AppPanelEmbed, true);
}

接下來你只需要這樣調(diào)用,便可以在編輯器中插入自定義的HTML塊:

quill.insertEmbed(quill.getSelection().index || 0, 'AppPanelEmbed', `
          <div class="app_card_header">     
              自定義面板標(biāo)題
          </div>
          <div class="app_card_content">     
              自定義面板內(nèi)容
          </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"';
          }
        },
      } // 自定義規(guī)則
      const myxss = new xss.FilterXSS(options)
      return myxss.process(content)
    }

到此這篇關(guān)于Quill編輯器插入自定義HTML記錄的文章就介紹到這了,更多相關(guān)Quill編輯器自定義HTML內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持腳本之家!

標(biāo)簽:山南 內(nèi)蒙古 陜西 廣安 上海 保定 清遠(yuǎn) 吳忠

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《Quill編輯器插入自定義HTML記錄的示例詳解》,本文關(guān)鍵詞  Quill,編輯器,插入,自定義,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請?zhí)峁┫嚓P(guān)信息告之我們,我們將及時溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《Quill編輯器插入自定義HTML記錄的示例詳解》相關(guān)的同類信息!
  • 本頁收集關(guān)于Quill編輯器插入自定義HTML記錄的示例詳解的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章