需求
需要一个可编辑的框,其中存在高亮的文字块,所有文字块默认高亮,但我执行删除操作,支持一次删除一个文字块,无论文字块里的字数多少
想法
首先排除用 input,然后问问AI,很棒,给出了关键要素,html 属性 contenteditable ,设置为 true 就代表着元素内部可以编辑内容,然后在元素内部的文字块标记起来——类,属性,元素名等都行。
实现
<div class="text-edit-container" contenteditable="true" ref="textEditRef">
123454我是正常字符<span class="pec-text-block">我是高亮</span>woshizhengcdre
</div>
.text-edit-container {
outline: 1px solid #e4e7ed;
border: none;
padding: 4px 8px;
height: 240px;
overflow: auto;
&:focus {
outline: 1px solid #409eff;
border-radius: 2px;
box-shadow: 2px 2px 12px 0 rgba(0, 0, 0, 0.05);
}
}
// 高亮元素
.pec-text-block {
user-select: none;
cursor: pointer;
color: #409eff;
border-radius: 2px;
background: #e6f7ff;
}
到这里基本就可以实现高亮元素了,然后是删除,删除的话就监听 backspace 按键事件,对光标位置进行判断,代码大致是AI写的,因为 range 这块不太熟
document.addEventListener('keydown', (event) => {
if (event.key === 'Backspace') {
const selection = window.getSelection();
let blockToRemove = null;
// 获取需要删除的文字块
if (selection.rangeCount > 0) {
const range = selection.getRangeAt(0);
// 判断 range.startContainer 是否为文本节点
if (range.startContainer.nodeType === Node.TEXT_NODE) {
blockToRemove = range.startContainer.parentNode; // 获取父节点
} else {
blockToRemove = range.startContainer;
}
}
// 如果光标在一个文字块内部或紧挨着文字块后面,则删除该文字块
if (blockToRemove && blockToRemove.classList.contains('pec-text-block')) {
blockToRemove.remove();
event.preventDefault();
}
}
}
})
// 记得注销
ok,到这里其实需求差不多结束,接下来就是我对要转高亮块的文字进行特殊处理,就没什么通用性了。
有一个问题
上面的代码高亮的文字块可以编辑,在转换的时候记得给元素加上 contenteditable=false 。