上一篇總結:
上一篇其實代碼開發方面,基本原理都看的差不多了,但是發生了無限嵌套的問題。
總結下富文本遇到的問題:
1、元素跨標籤處理
2、如何正確選擇到你要的元素
3、跨行設置元素未選中部分換行(默認回車事件導致)
4、多個功能直接交叉使用問題(要有取捨)
5、css新舊混合問題
6、代碼塊插入問題
7、其實還有更多問題,但是沒有開發過的那真的不知其中各種滋味…………
目前還未解決的問題:
實現csdn的回車標籤(這個問題比較特殊,操作太多之後會樣式滯留,還有就是回車無法順利回車的問題都需要單獨的回車操作)
這裏希望csdn的開發組看到之後,能告訴下我csdn的富文本的回車操作怎麼實現的。現在沒有思緒
核心代碼部分:
這個是我認爲的最核心操作部分,這裏最核心的就是文檔片段的操作。
因爲操作原理在於先得到你選中的元素,然後再操作這部分元素,再重新插入進去。(先選後得到元素處理,然後刪除重新插入,先刪後插)
我的代碼沒做什麼兼容性,從上一次開發到現在滿打滿算其實是一週的樣子。
還有一個比較關鍵的代碼是,基本上自定義的操作都是靠這個api來實現的。
document.execCommand("insertHTML", false, `<br>`);
import { CursorAcquisition } from "./selection";
import { delCss } from "./tool";
//文檔片段處理
const domFragmentHandle = () => {
const { range } = CursorAcquisition();
//獲取需要操作的元素進行處理
let domst = range.commonAncestorContainer;
domst = domst.nodeType === 1 ? domst : domst.parentNode;
//獲取元素中的css屬性getSelectionText
let cssText = domst.style.cssText;
let innerhtml = "";
console.log("當前獲取的節點", domst.nodeName);
//處理節點名稱,若果爲指定的元素則返回空
let nodeName = domst.nodeName;
let nodelist = ["div"];
if (nodelist.indexOf(nodeName.toLocaleLowerCase()) !== -1) {
nodeName = "";
}
nodeName = nodeName.toLocaleLowerCase();
//判斷處理,如果父節點是最大的div則更換選取方式
if (domst.id === "dht-editor-content") {
let span = document.createElement("span");
let elem = range.cloneContents();
span.appendChild(elem);
innerhtml = span.innerHTML;
} else {
//console.log(domst.childNodes);
//dom元素處理,不要多餘標籤,將字符串抽離,但是注意保持文檔結構,
// 但是該操作會導致多行的文檔縮進等無效
let child = domst.childNodes;
for (let i = 0; i < child.length; i++) {
if (child[i].nodeName === "BR") {
innerhtml += `<br>`;
} else {
let node = child[i];
innerhtml += node.nodeValue ? node.nodeValue : node.innerText;
}
}
}
//最終返回需要的元素
return {
innerhtml,
cssText,
nodeName
};
};
//獨立選中區域文字
const getSelectionText = () => {
const { range } = CursorAcquisition();
//獲取元素中的css屬性
let cssText = "";
let span = document.createElement("span");
let elem = range.cloneContents();
span.appendChild(elem);
let innerhtml = span.innerHTML;
//最終返回需要的元素
return {
innerhtml,
cssText
};
};
//最終執行函數
const execOperation = (name, value = null) => {
const { range } = CursorAcquisition();
if (!range.toString()) {
console.log("未選中任何元素");
return false;
}
let bool = document.execCommand(name, false, value);
range.detach();
return bool;
};
//生成html字符串
//傳入參數:
/*
* 插入的節點名稱,
* style:del: 需要刪除的css名稱
* css:最後應用的css
* */
const combinationHtml = style => {
const { innerhtml, cssText, nodeName } = domFragmentHandle();
let delcss = style.del || "";
let css = style.css || "";
let node = style.node || "span";
let url = style.url;
//let html = style.html || `<${node} style="${oldCss}; ${css}">${innerhtml}</${node}>`
//之前的css
let oldCss = cssText ? delCss(cssText, delcss) : "";
console.log("html處理得到", nodeName);
//新老節點判斷處理,特殊的節點需要使用老節點比如span無法和h2混合
if (nodeName && node !== nodeName && node !== "a") {
node = nodeName;
}
//定義需要插入的html元素
let html = "";
if (node === "a") {
html = `<${node} href="${url}" style="${oldCss}; ${css}">${innerhtml}</${node}>`;
} else {
html = `<${node} style="${oldCss}; ${css}">${innerhtml}</${node}>`;
}
console.log(html);
return html;
};
export { domFragmentHandle, execOperation, getSelectionText, combinationHtml };
個人git地址:
https://github.com/ht-sauce/dream
富文本文件地址:
dream/src/components/richTextEditor/
訪問地址:http://localhost:8080/dht_blog/richTextEditor
中間開發到一半吧有點想放棄:
原因在於我加了wang富文本的羣,裏面一個開發說,你這樣沒意義,浪費時間,還大言不慚的說給我一年時間我也能寫一個(關愛zhizhang),說實在我到現在爲止完全沒有什麼幫助,還好有wang富文本開源。(感謝)
獻上wang富文本地址:http://wangeditor.com