你好,我是 Kagol,個人公眾號:前端開源星球
。
2024年8月20日,剛開源一週的富文字 Fluent Editor 迎來了第一位貢獻者:zzxming
1 Bug 描述
zzxming 同學修復了 Fluent Editor 富文字表格模組的一個隱藏 Bug:
fix: table module can't save background color #10
缺陷描述:透過表格右鍵選單設定單元格背景色之後,生成的 delta 中缺失單元格背景色資訊,導致透過 setContents 方法設定的富文字表格單元格丟失了背景色。
這樣描述可能比較繞口,zzxming 同學非常貼心地做了一個 Demo 用於復現該問題:
最小可復現 Demo
2 Bug 復現步驟
第一步:在表格單元格中右鍵,給單元格設定一個背景色。
第二步:透過 editor.getContents() 獲取到的對應的 delta。
const delta = {
"ops": [
{
"attributes": {
"table-col": {
"width": "100"
}
},
"insert": "\n"
},
{
"attributes": {
"table-cell-line": {
"rowspan": "1",
"colspan": "1",
"row": "row-xapy",
"cell": "cell-e89w"
},
"row": "row-xapy",
"cell": "cell-e89w",
"rowspan": "1",
"colspan": "1"
},
"insert": "\n"
}
]
}
可以看到 delta 沒有攜帶單元格背景色資訊。
第三步:將 delta 透過 setContents 方法回填到富文字中,單元格沒有背景色。
editor.setContents(delta)
3 解決方案
修改檔案:packages/fluent-editor/src/table/formats/table.ts
修復該問題主要分成以下步驟:
- 把 delta 中的 cell-bg 設定到 qlbt-cell-line 節點的
data-cell-bg
屬性中 - 從 qlbt-cell-line 節點中拿到
data-cell-bg
的值,回填到單元格背景色 - 將 DOM 節點中的
data-cell-bg
值,儲存到 delta 中
3.1 將 delta 中 cell-bg 資訊設定到 DOM 節點中
將 delta 資訊設定到 DOM 節點中,一般是在 blot 的
static create
方法中進行。
static create(value) {
const node = super.create(value);
...
- CELL_ATTRIBUTES.forEach((attrName) => {
- node.setAttribute(`data-${attrName}`, value[attrName] || CELL_DEFAULT[attrName]);
+ [...CELL_ATTRIBUTES, 'cell-bg'].forEach((attrName) => {
+ const keyValue = value[attrName] || CELL_DEFAULT[attrName];
+ keyValue && node.setAttribute(`data-${attrName}`, keyValue);
});
...
return node;
}
先從 delta(value) 中拿到 cell-bg 資訊,然後設定到 DOM 節點的 data-cell-bg 屬性中。
value 的結構:
{
rowspan: '1',
colspan: '1',
row: 'row-xapy',
cell: 'cell-e89w',
cell-bg: '#ffff00'
}
3.2 回填 cell-bg 到單元格背景色
zzxming
同學不僅修復了這個 Bug,還做了一個小重構,將設定單元格背景色這個功能抽成了一個函式 setCellBg
,並且加了詳細的註釋,點贊👍
/** this method is for TableCellLine to change cell background color
* if use `format('cell-bg', value)` will loop trigger
* TableCellLine.optimize -> TableCell.format -> TableCellLine.optimize ...
*/
setCellBg(value?: string) {
if (value) {
this.domNode.style.backgroundColor = value
} else {
this.domNode.style.backgroundColor = 'initial'
}
}
在 TableCellLine 類的 optimize 方法中呼叫該函式,以便把 delta 中的 cell-bg 顏色設定到表格單元格。
3.3 將 cell-bg 資訊儲存到 delta 中
將 DOM 的資訊儲存到 delta 中,一般是在 blot 的
static format
方法中進行。
在 TableCellLine 類的 static format 方法中呼叫了 reduceFormats 函式,給該函式傳入 cell-bg 資訊。
static formats(domNode) {
const formats = {};
if (formats['list']) {
formats['list'] = domNode.classList.item(0);
}
- return reduceFormats(domNode, formats);
+ return reduceFormats(domNode, formats, ['cell-bg']);
}
在 reduceFormats 中獲取到 DOM 中的 data-cell-bg,並設定到 delta 資料中。
- function reduceFormats(domNode, formats) {
- return CELL_ATTRIBUTES.concat(CELL_IDENTITY_KEYS).reduce((tableFormats, attribute) => {
+ function reduceFormats(domNode:HTMLElement, formats:Record<string, any>, extraFormat: string[] = []) {
+ return [...CELL_ATTRIBUTES, ...CELL_IDENTITY_KEYS, ...extraFormat].reduce((tableFormats, attribute) => {
if (domNode.hasAttribute(`data-${attribute}`)) {
tableFormats[attribute] = domNode.getAttribute(`data-${attribute}`) || undefined;
}
return tableFormats;
}, formats);
}
該問題已解決,可以透過以下連結進行驗證:
- https://stackblitz.com/edit/vitejs-vite-cakzv5?file=src%2FApp.vue
詳見 zzxming 同學提交的 PR:
fix: table module can't save background color #10
3.4 最佳化點
這裡其實有個最佳化點(歡迎 PR 👏):
目前 zzxming 同學在 static create 和 reduceFormats 方法中傳入 cell-bg 都是直接增加的,其實可以放到 CELL_ATTRIBUTES 常量陣列中,合理利用現有的程式碼😋。
- export const CELL_ATTRIBUTES = ['rowspan', 'colspan'];
+ export const CELL_ATTRIBUTES = ['rowspan', 'colspan', 'cell-bg'];
感謝 zzxming 同學對 Fluent Editor 的貢獻,目前已釋出 v3.18.3 版本,歡迎朋友們使用 Fluent Editor,感興趣也歡迎一起參與共建。
往期文章推薦:
- Fluent Editor:一個基於 Quill 2.0 的富文字編輯器,功能強大、開箱即用!
- 重回鐵王座!時隔5年!Quill 2.0 終於釋出啦
- 深入淺出 Quill 系列之使用篇1:Quill 基本使用和配置
- 深入淺出 Quill 系列之使用篇2:透過 Quill API 實現對編輯器內容的完全控制
- 深入淺出 Quill 系列之原理篇1:現代富文字編輯器 Quill 的模組化機制
- 深入淺出 Quill 系列之原理篇2:現代富文字編輯器 Quill 的內容渲染機制
- 深入淺出 Quill 系列之實踐篇1:如何將龍插入到編輯器中?
- 深入淺出 Quill 系列之實踐篇2:整個貪吃蛇遊戲到編輯器裡玩兒吧
- 深入淺出 Quill 系列之選型篇:Quill 富文字編輯器的實踐
聯絡我們
GitHub:https://github.com/opentiny/tiny-vue(歡迎 Star ⭐)
官網:https://opentiny.design/tiny-vue
B站:https://space.bilibili.com/15284299
個人部落格:https://kagol.github.io/blogs
小助手微信:opentiny-official
公眾號:OpenTiny