這篇文章主要介紹了Quill編輯器插入自定義HTML記錄的示例詳解,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧
轉眼已經2020年,饑渴的人類不再滿足于簡單的文本,于是有了花里胡哨的攜帶各種樣式的文本,然而有文本還不夠,我們還需要讓用戶在編輯的時候,能夠插入各種自定義消息類型,讓我們發(fā)出去的軟文更加好看,因此有了這篇文章。
前言
由于Quill編輯器自帶的富文本過濾(大部分主流編輯器都會對富文本進行過濾處理),導致開發(fā)者想要配置自定義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個字符,對后續(xù)的20個字符進行加粗操作的delta如下:
{
"ops": [
{ "retain": },
{ "retain": , "attributes": { "bold": } }
]
}
保留前10個字符,對后續(xù)的20個字符進行刪除操作如下:
{
"ops": [
{ "retain": },
{ "delete": }
]
}
2、Parchment
Parchment是抽象的文檔模型,對Blot進行管理。
將Parchment理解成完整的DOM樹結構的話,那么Blot就是其中一個個單一的節(jié)點。而Blot去了Quill中默認的以外,還允許我們進行自定義,給了更大的擴展空間。
3、Blot
Blot是Parchment文檔的組成部分,相當于對DOM節(jié)點類型的抽象,而一個具體的Blot實例里仍有其他的節(jié)點信息。
全局的根節(jié)點Blot是由Quill內部自定義的Scroll類型Blot,管理其下面的所有Blot。
對于Blot的實現(xiàn)定義可以參照這里: https://github.com/quilljs/parchment#blots
Quill中默認定義的Blot如下:
這其中常見的包括TextBlot(行內普通文本)、Inline(行內攜帶樣式的普通文本)、Block(塊級行,一般以段落p為單位)、Break(換行)、Image(圖片IMG插入)、Bold(加粗文本)。
而一段HTML如何構建出Blot?Quill中會根據節(jié)點類型優(yōu)先排除文本節(jié)點,如果是元素節(jié)點會根據節(jié)點的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節(jié)點回顯與頁面中。
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監(jiān)聽處理,更新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('')
}
// 返回節(jié)點自身的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"';
}
},
} // 自定義規(guī)則
const myxss = new xss.FilterXSS(options)
return myxss.process(content)
}
到此這篇關于Quill編輯器插入自定義HTML記錄的文章就介紹到這了,更多相關Quill編輯器自定義HTML內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持腳本之家!
來源:腳本之家
鏈接:https://www.jb51.net/web/733567.html
申請創(chuàng)業(yè)報道,分享創(chuàng)業(yè)好點子。點擊此處,共同探討創(chuàng)業(yè)新機遇!