上一篇总结:
上一篇其实代码开发方面,基本原理都看的差不多了,但是发生了无限嵌套的问题。
总结下富文本遇到的问题:
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