js 进行在线编辑器开发
基于 textarea 开发的 markdown 编辑器
textarea
最简单,但是可以编辑的内容也少。
需要的了解的知识
const element: HTMLTextAreaElement;
element.selectionStart // 获取或设置选中的起始位置
element.selectionEnd // 获取或设置选中的结束位置
// 获取选中的文字
const v = element.value;
const selectValue = v.substring(element.selectionStart, element.selectionEnd);
// 替换选中的内容
const replace = '';
element.value = v.substring(0, element.selectionStart) + replace + v.substring(element.selectionEnd);
// 移动光标到指定位置,移动光标到开始位置
element.selectionStart = 0
element.selectionEnd = 0
// 移动光标到结尾
element.selectionStart = element.value.length
element.selectionEnd = element.value.length
// 需要把焦点设置到元素,才会显示光标
element.focus();
textarea
只接受字符串,所以图片,超链接等需要使用 markdown 格式转成对应的字符串
基于 div 开发的 富文本编辑器
把div 设置为可编辑模式
需要了解的知识
- 默认换行是自动添加 '<div><br></div>'
- 获取选中
const element: HTMLDivElement;
const sel = window.getSelection();
const range = sel.getRangeAt(0);
// range 就是当前选中的内容了
range.startContainer // 选中的起始节点
range.startOffset // 在起始节点的具体位置
range.endContainer // 选中的结束节点
range.startOffset // 在结束节点的具体位置
// 当未选中任何内容时
range.startContainer === range.endContainer && range.startOffset === range.endOffset
range.startContainer // 节点的类型,有 Text 、HtmlElement
range.startOffset // 当 节点类型为 Text 时,则为字符串的位置, 当为 HtmlElement 时,则为在节点中子元素的位置, 例如0 则是元素的最前面
// 选中 区域
const sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(selectRange);
// 选中指定元素
const selectRange = document.createRange();
// 选中整个元素
selectRange.selectNodeContents(element);
// 选中元素的一部分
selectRange.setStart(element, 0);
selectRange.setEnd(element, 0);
sel.removeAllRanges();
sel.addRange(selectRange);
// 截断字符串节点
const node: Text
node.splitText(offset) // 返回新创建的后一部分字符串的节点, 自动会添加到页面上的
基于 div 开发的 代码编辑器
相对来说,代码编辑器相对简单,就只要 显示对应行号、对部分字符串加样式即可,当然更高级的需要加代码提示候选就更复杂点了。
基本逻辑
- 对回车进行换行处理,实际就是在选择的地方切断,把后面一部分放到另一行
- 新增行,需要同时增加行号,及在行号列表中增加新的一行,并同时个更新后面的行号
- 对行的高度要跟行号的高度进行同步
- 缩进或者文字输入需要提取整行内容进行处理
let isComposition = false; // 判断是否是输入法输入
element.addEventListener('keydown', e => {
});
element.addEventListener('keyup', () => {
if (isComposition) {
return;
}
});
element.addEventListener('compositionstart', () => {
isComposition = true;
});
element.addEventListener('compositionend', () => {
isComposition = false;
});
- div 的尺寸变化要进行行号高度更新
let lastHeight = 0;
const resizeObserver = new ResizeObserver(entries => {
for (const item of entries) {
if (item.contentRect.height === lastHeight) {
continue;
}
if (lastHeight === 0) {
// 这里的意思是, 显示隐藏切换时进行高度更新
this.updateLineNoStyle();
}
lastHeight = item.contentRect.height;
}
});
resizeObserver.observe(element);
转载请保留原文链接: https://zodream.cn/blog/id/243.html