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

如何从选中文本判断节点名称?含文本加粗切换场景需求

实现文本选中后的加粗切换与节点识别

嘿,这个需求完全可以搞定!咱们一步步来拆解:首先要解决如何识别选中文本对应的节点,然后再实现加粗切换的逻辑。

一、识别选中文本的节点类型/名称

要判断选中内容对应的节点,核心是利用浏览器的Selection和Range API,这俩是处理文本选区的关键工具。

1. 获取当前选区

首先通过window.getSelection()拿到当前的选区对象,然后获取对应的选区范围:

const selection = window.getSelection();
if (selection.rangeCount === 0) return; // 没有选中内容就直接退出
const range = selection.getRangeAt(0);

2. 判断选中内容对应的节点

这里分两种场景对应你的需求:

  • 选中内容完全在单个节点内(比如选中Foo,完全在<span>里;选中Bar,完全在<p>里):
    用range.commonAncestorContainer获取选中内容的最内层共同祖先节点,注意区分文本节点和元素节点:
    const targetNode = range.commonAncestorContainer;
    // 文本节点的nodeType是3,要拿到它的父元素节点
    const elementNode = targetNode.nodeType === 3 ? targetNode.parentElement : targetNode;
    
    console.log('当前选中内容对应的节点名称:', elementNode.tagName.toLowerCase());
    // 比如选中Foo会输出span,选中Bar会输出p
    
  • 选中内容跨多个节点(比如选中Foo B,一部分在<span>,一部分在<p>的文本节点):
    这时候commonAncestorContainer会返回它们的共同父节点(也就是<p>),刚好符合你要识别为p节点的需求。

二、实现文本加粗切换功能

有了节点识别的基础,咱们来实现“未加粗则加粗,已加粗则取消”的逻辑:

1. 判断选中内容是否已加粗

递归检查节点是否被<b>或<strong>标签包裹:

function isTextBold(node) {
  while (node && node.tagName) {
    if (node.tagName.toLowerCase() === 'b' || node.tagName.toLowerCase() === 'strong') {
      return true;
    }
    node = node.parentElement;
  }
  return false;
}

2. 执行加粗/取消加粗操作

function toggleBold() {
  const selection = window.getSelection();
  if (selection.rangeCount === 0) return;
  const range = selection.getRangeAt(0);
  const targetNode = range.commonAncestorContainer;
  const elementNode = targetNode.nodeType === 3 ? targetNode.parentElement : targetNode;

  if (isTextBold(elementNode)) {
    // 已加粗,取消:把加粗标签的内容移到父节点,再移除加粗标签
    const boldNode = elementNode.closest('b, strong');
    const parent = boldNode.parentElement;
    while (boldNode.firstChild) {
      parent.insertBefore(boldNode.firstChild, boldNode);
    }
    parent.removeChild(boldNode);
  } else {
    // 未加粗,添加加粗标签
    const bold = document.createElement('strong');
    try {
      range.surroundContents(bold);
    } catch (e) {
      // 处理跨节点选中的异常情况,比如直接给选中内容包裹加粗标签
      const fragment = range.extractContents();
      bold.appendChild(fragment);
      range.insertNode(bold);
    }
  }
  // 恢复选区,避免操作后选区丢失
  selection.removeAllRanges();
  selection.addRange(range);
}

3. 绑定触发事件

比如给按钮绑定点击事件:

<button onclick="toggleBold()">切换加粗</button>
<p>
  <span>Foo</span> Bar
</p>

注意事项

  • 跨节点选中时,range.surroundContents()可能抛出异常,代码里加了try-catch处理这种情况,确保功能正常运行。
  • 一定要区分文本节点(nodeType=3)和元素节点,不然会误拿到#text节点而不是你需要的<span>或<p>。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 09:02:27