如何从选中文本判断节点名称?含文本加粗切换场景需求
实现文本选中后的加粗切换与节点识别
嘿,这个需求完全可以搞定!咱们一步步来拆解:首先要解决如何识别选中文本对应的节点,然后再实现加粗切换的逻辑。
一、识别选中文本的节点类型/名称
要判断选中内容对应的节点,核心是利用浏览器的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
相关产品推荐
相关产品推荐

