You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

不使用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();
}

效果验证

  1. 选中"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>
    
  2. 选中整个句子点击按钮:
    <u>标签会被直接移除,变为普通文本:

    Hello, my name is Justin, and I have a question
    

注意事项

  • 代码适配了contenteditable可编辑区域,普通静态元素同样适用
  • 若存在多层嵌套的<u>元素,可扩展逻辑遍历所有嵌套节点处理
  • 文本节点拆分依赖splitText方法,需确保操作的是文本类型节点

内容的提问来源于stack exchange,提问作者Justin Black

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 14:06:18