不使用document.execCommand('removeFormat')移除选中Range的下划线
实现选中内容的下划线移除功能
要实现选中内容移除下划线的功能,你可以通过原生JavaScript处理选区和DOM节点,分场景处理选区与<u>元素的关系:
核心逻辑
根据选区和<u>元素的覆盖关系,分三种情况处理:
- 选区完全包裹
<u>元素:直接移除<u>标签,保留内部文本 - 选区部分覆盖
<u>元素:将<u>拆分为未选中的前后两段,选中区域转为无下划线的普通文本 - 选区位于
<u>元素内部:拆分<u>为前(带下划线)、中(无下划线)、后(带下划线)三段
代码实现
先准备基础HTML结构:
<div contenteditable="true" id="editor"> <u> Hello, my name is Justin, and I have a question </u> </div> <button onclick="removeUnderlineFromSelection()">取消下划线</button>
然后编写处理函数:
function removeUnderlineFromSelection() { const selection = window.getSelection(); if (selection.rangeCount === 0) return; // 无选中内容直接返回 const range = selection.getRangeAt(0).cloneRange(); const parentU = range.commonAncestorContainer.closest('u'); const allUs = Array.from(range.commonAncestorContainer.querySelectorAll('u')); // 处理完全被选中的<u>元素 allUs.forEach(u => { const uRange = document.createRange(); uRange.selectNodeContents(u); if (range.compareBoundaryPoints(Range.START_TO_START, uRange) <= 0 && range.compareBoundaryPoints(Range.END_TO_END, uRange) >= 0) { u.replaceWith(...u.childNodes); } }); // 处理部分覆盖的<u>元素 if (parentU) { const startInU = parentU.contains(range.startContainer); const endInU = parentU.contains(range.endContainer); if (startInU || endInU) { // 拆分起始位置的文本节点 if (startInU && range.startContainer.nodeType === Node.TEXT_NODE) { const splitStart = range.startContainer.splitText(range.startOffset); const newU = document.createElement('u'); newU.appendChild(parentU.firstChild); parentU.parentNode.insertBefore(newU, parentU); parentU.replaceChild(splitStart, parentU.firstChild); } // 拆分结束位置的文本节点 if (endInU && range.endContainer.nodeType === Node.TEXT_NODE) { const splitEnd = range.endContainer.splitText(range.endOffset); const newU = document.createElement('u'); newU.appendChild(splitEnd); parentU.parentNode.insertBefore(newU, parentU.nextSibling); parentU.removeChild(splitEnd); } // 移除中间选中部分的<u>标签 parentU.replaceWith(...parentU.childNodes); } } selection.removeAllRanges(); }
效果验证
选中"Justin, and I"点击按钮:
原HTML:<u> Hello, my name is Justin, and I have a question </u>执行后变为:
<u> Hello, my name is </u> Justin, and I <u> have a question </u>选中整个句子点击按钮:
<u>标签会被直接移除,变为普通文本:Hello, my name is Justin, and I have a question
注意事项
- 代码适配了
contenteditable可编辑区域,普通静态元素同样适用 - 若存在多层嵌套的
<u>元素,可扩展逻辑遍历所有嵌套节点处理 - 文本节点拆分依赖
splitText方法,需确保操作的是文本类型节点
内容的提问来源于stack exchange,提问作者Justin Black
相关产品推荐
相关产品推荐

