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

如何为选中文本添加标签并在其前后闭合/重开父标签?

实现富文本编辑器中选中文字的同级样式拆分

你当前的代码会生成嵌套的span结构,要实现同级拆分的效果,需要把原父元素拆分为三个同级span:保留原样式的前半部分、应用新样式的选中部分、保留原样式的后半部分。具体实现如下:

目标效果对比

原始HTML:

<span class="text-3xl">Foo</span>

期望输出:

<span class="text-3xl">F</span><span class="text-sm">o</span><span class="text-3xl">o</span>

解决方案代码

function splitTextWithStyle(targetClass) {
  // 检查是否有有效选区
  const selection = window.getSelection();
  if (selection.rangeCount === 0) return;
  const range = selection.getRangeAt(0);

  // 获取选中内容的直接父span(确保操作对象正确)
  const parentSpan = range.commonAncestorContainer.closest('span');
  if (!parentSpan) return;

  // 拆分内容:选中前、选中内容、选中后
  const selectedContent = range.extractContents();

  // 提取选中部分之前的内容
  const beforeRange = document.createRange();
  beforeRange.setStart(parentSpan.firstChild, 0);
  beforeRange.setEnd(range.startContainer, range.startOffset);
  const beforeContent = beforeRange.extractContents();

  // 提取选中部分之后的内容
  const afterRange = document.createRange();
  afterRange.setStart(range.endContainer, range.endOffset);
  afterRange.setEnd(parentSpan.lastChild, parentSpan.lastChild.length);
  const afterContent = afterRange.extractContents();

  // 创建三个同级span
  const beforeSpan = document.createElement('span');
  beforeSpan.className = parentSpan.className;
  beforeSpan.appendChild(beforeContent);

  const middleSpan = document.createElement('span');
  middleSpan.className = targetClass;
  middleSpan.appendChild(selectedContent);

  const afterSpan = document.createElement('span');
  afterSpan.className = parentSpan.className;
  afterSpan.appendChild(afterContent);

  // 用新的三个span替换原父span
  const fragment = document.createDocumentFragment();
  fragment.append(beforeSpan, middleSpan, afterSpan);
  parentSpan.parentNode.replaceChild(fragment, parentSpan);

  // 可选:恢复选区到新样式的文本上
  const newRange = document.createRange();
  newRange.selectNodeContents(middleSpan);
  selection.removeAllRanges();
  selection.addRange(newRange);
}

关键逻辑说明

  • 内容拆分:通过Range对象的extractContents()方法,精准拆分出选中区域的前、中、后三部分内容,避免嵌套结构。
  • 元素重建:为前、后部分创建与原父元素同样式的span,中间部分应用目标样式,确保三者同级。
  • 替换节点:使用文档片段一次性插入三个span,减少DOM操作次数,提升性能。
  • 选区恢复:可选步骤,让用户操作后保持对新样式文本的选中状态,优化交互体验。

内容的提问来源于stack exchange,提问作者Sven Lueck

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 18:34:55